0%

Codeforces Div 2 D 天梯 26——30

http://codeforces.com/contest/442/problem/B 自己试图用调整法搞了半天...然而并没有推出来.... 后来参考了一下题解的式子... http://codeforces.com/blog/entry/12739 有个这个式子之后,这个问题就很好解决了,只要保持\(S\) 小于 1 就行了... 果然数学弱的一逼...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include<bits/stdc++.h>
using namespace std;
int n;
double p[110]={};
double u;
double p1,p0,t1,t0;
bool cmp(double x,double y)
{
return x>y;
}
double s;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>p[i];
u=max(u,p[i]);
}
if(u>=0.5)
{
printf("%.10lf",u);
return 0;
}
else
{
p1=0.0;
p0=1.0;
sort(p+1,p+n+1,cmp);
s=0.0;
for(int i=1;i<=n;i++)
{
if(s>=1.0) break;
p1=p1*(1-p[i])+p0*p[i];
p0=p0*(1-p[i]);
s+=p[i]/(1-p[i]);
}
}
printf("%.10lf",p1);
return 0;
}

http://codeforces.com/contest/446/problem/B 只要能够发现,这个东西先算行和先算列对结果不产生任何影响就可以了... 然后先贪心行、再贪心列,或者行列一起贪一贪,再减掉需要减的就可以了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include<bits/stdc++.h>
using namespace std;
struct cmp{
bool operator ()(int &a,int &b){
return a<b;
}
};
priority_queue<int,vector<int>,cmp> qr;
priority_queue<int,vector<int>,cmp> qc;
long long r[1000010]={};
long long c[1000010]={};
long long n,m,k,t;
long long a[1010][1010]={};
long long p;
long long ans;
int main()
{
cin>>n>>m>>k>>t;
for(int i=1;i<=n;i++)
{
p=0;
for(int j=1;j<=m;j++)
{
cin>>a[i][j];
p+=a[i][j];
}
qr.push(p);
}
for(int j=1;j<=m;j++)
{
p=0;
for(int i=1;i<=n;i++)
{
p+=a[i][j];
}
qc.push(p);
}
for(int i=1;i<=k;i++)
{
r[i]=r[i-1];
p=qr.top();
r[i]+=p;
qr.pop();
p-=m*t;
qr.push(p);
}
for(int i=1;i<=k;i++)
{
c[i]=c[i-1];
p=qc.top();
c[i]+=p;
qc.pop();
p-=n*t;
qc.push(p);
}
ans=-223372036854775808;
for(int i=0;i<=k;i++)
{
p=k-i;
ans=max(ans,r[i]+c[p]-p*i*t);
}
cout<<ans;
return 0;
}

http://codeforces.com/problemset/problem/274/B 从树的底部一直推到树的最上边 记录一下从这个节点往下所有节点都变成0的时候的,至少要做几次+1,至少要做几次-1 然后往上一个节点更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include<bits/stdc++.h>
using namespace std;
long long v[100010]={};
vector<int> e[100010];
int a,b;
int n;
bool vis[100010]={};
int d[100010]={};
queue<int> q;
long long pbu[100010]={};
long long dbu[100010]={};
long long bian[100010]={};
int g,p;
int main()
{
scanf("%d",&n);
d[1]=1000;
for(int i=1;i<n;i++)
{
scanf("%d%d",&a,&b);
e[a].push_back(b);
e[b].push_back(a);
d[a]++;
d[b]++;
}
for(int i=1;i<=n;i++)
{
scanf("%I64d",&v[i]);
}
for(int i=1;i<=n;i++)
{
if(d[i]==1)
{
q.push(i);
vis[i]=1;
bian[i]=-v[i];
if(bian[i]<0) dbu[i]+=abs(v[i]);
else pbu[i]+=abs(v[i]);
}
}
while(!q.empty())
{
g=q.front();
q.pop();
for(int i=0;i<e[g].size();i++)
{
p=e[g][i];
if(vis[p]==0)
{
d[p]--;
int f=0;
if(pbu[g]>pbu[p])
{
f+=pbu[g]-pbu[p];
pbu[p]=pbu[g];
}
if(dbu[g]>dbu[p])
{
f-=dbu[g]-dbu[p];
dbu[p]=dbu[g];
}
bian[p]+=f;
if(d[p]==1)
{
vis[p]=1;
v[p]+=bian[p];
bian[p]=-v[p];
if(v[p]>0)
{
dbu[p]+=v[p];
}
else
{
pbu[p]+=abs(v[p]);
}
q.push(p);
}
}
}
}
v[1]+=bian[1];
if(v[1]>0)
{
dbu[1]+=v[1];
}
else
{
pbu[1]+=abs(v[1]);
}
cout<<dbu[1]+pbu[1];
return 0;
}

http://codeforces.com/problemset/problem/432/D 用到了好多kmp的思想... 先求一下前向数组...然后每一个前向数组对应的值记录一下有多少个... 用前向数组更新前缀后缀相同的长度,然后不停更新个数... 感觉用语言好难描述啊...具体看代码吧...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include<bits/stdc++.h>
using namespace std;
string s;
int p[100010]={};
char b[100010]={};
int num[100010]={};
int t;
stack<int> an;
stack<int> nu;
int main()
{
cin>>s;
for(int i=1;i<=s.size();i++) b[i]=s[i-1];
p[1]=0;
int j=0;
for(int i=2;i<=s.size();i++)
{
while((j>0)&&(b[j+1]!=b[i])) j=p[j];
if(b[j+1]==b[i]) j++;
p[i]=j;
}
t=p[s.size()];
for(int i=1;i<=s.size();i++)
{
num[p[i]]++;
}
t=p[s.size()];
int o;
int pr;
for(int i=s.size();i>t;i--)
{
num[p[i]]+=num[i];
}
while(t!=0)
{
o=1+num[t];
an.push(t);
nu.push(o);
pr=t;
t=p[t];
for(int i=pr;i>t;i--)
{
num[p[i]]+=num[i];
}
}
cout<<an.size()+1<<endl;
while(!an.empty())
{
cout<<an.top()<<" "<<nu.top()<<endl;
an.pop();
nu.pop();
}
cout<<s.size()<<" "<<1<<endl;
return 0;

}

http://codeforces.com/problemset/problem/91/B 裸set题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include<bits/stdc++.h>
using namespace std;
int n;
int a[100010]={};
int ans[100010]={};
set<pair<int,int>> s;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
s.insert(make_pair(0,n+1));
for(int i=n;i>=1;i--)
{
set<pair<int,int>>::iterator p;
p=s.lower_bound(make_pair(a[i],i));
if(p==s.end())
{
p--;
if((*p).first==0)
{
ans[i]=-1;
s.insert(make_pair(a[i],i));
}
else
{
ans[i]=(*p).second-i-1;
}
}
else
{
p--;
if((*p).first!=0) ans[i]=(*p).second-i-1;
else
{
ans[i]=-1;
s.insert(make_pair(a[i],i));
}
}
}
for(int i=1;i<=n;i++)
{
printf("%d ",ans[i]);
}
return 0;
}