Codeforces Round #525 (Div. 2)

A. Ehab and another construction problem

1不行 然后没了

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     int x;
 6     cin>>x;
 7     if(x==1)cout<<x-2;
 8     else cout<<x<<" "<<x;
 9     return 0;
10 }
View Code

B. Ehab and subtraction

排序 找不同数字 相减就行 考虑下够不够k

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int a[100001];
 4 int b[100001];
 5 int main()
 6 {
 7     int n,k;
 8     cin>>n>>k;
 9     int i,j;
10     for(i=1;i<=n;i++)
11     {
12         cin>>a[i];
13     }
14     sort(a+1,a+n+1);
15     j=1;
16     for(i=1;i<=n;i++)
17         if(a[i]!=a[i-1])
18     {
19         b[j]=a[i];
20         j++;
21     }
22     for(i=1;i<j&&i<=k;i++)
23         cout<<b[i]-b[i-1]<<endl;
24     for(i=j;i<=k;i++)
25         cout<<"0\n";
26     return 0;
27 }
View Code

C. Ehab and a 2-operation task

想办法构造1,2,3,4,5......

然后一个显然的地方 模数大于前面i-1个数 那个2操作只对最后一个有影响 所以先把所有数加一个大数 然后取模构造就行了

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n;
 4 int a[2001];
 5 int main(){
 6     cin>>n;
 7     cout<<n+1<<endl;
 8     cout<<"1 "<<n<<" 8000\n";
 9     for(int i=1;i<=n;i++)
10         {
11             cin>>a[i];
12             cout<<"2 "<<i<<" "<<8000+a[i]-i<<endl;
13         }
14     return 0;
15 }
View Code

D. Ehab and another another xor problem

假如我们知道a和b后面x位的大小关系,并且前面的已经求出来了,那么考虑当前位。

如果是00 11那么他们和01,10取异或后结果必相反

如果是01 10那么他们和01,10取异或后结果必相同

所以就可以用两次异或求出首位是否相同 相同则讨论两次结果 都x+1位大小关系不变

如果不同 那么大的数此为为1 小的为0 x+1位大小关系就是跟01或10异或的结果

最后 注意输出fflush(stdout)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main(){
 4     int a=0,b=0,f,x,y;
 5     printf("? 0 0\n");
 6     fflush(stdout);
 7     scanf("%d",&f);
 8     for(int i=29;i>=0;i--)
 9     {
10         printf("? %d %d\n",a^(1<<i),b);
11         fflush(stdout);
12         scanf("%d",&x);
13         printf("? %d %d\n",a,b^(1<<i));
14         fflush(stdout);
15         scanf("%d",&y);
16         if(x==y)
17         {
18             if(f==1)
19                 a^=(1<<i);
20             else
21                 b^=(1<<i);
22             f=x;
23         }
24         else
25         {
26             if(x==-1)
27                 a^=(1<<i),b^=(1<<i);
28         }
29     }
30     printf("! %d %d\n",a,b);
31     fflush(stdout);
32     return 0;
33 }
View Code

E. Ehab and a component choosing problem

两遍树形dp 第一遍找最值 第二遍找数量 就是当子树最值为答案是返回0给上一层

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn=300100;
 5 ll ans = -1e18;
 6 vector<int> G[maxn];
 7 ll v[maxn];
 8 int n;
 9 ll k;
10 ll dfs(int u,int f){
11     ll x=v[u];
12     for(int i=0;i<G[u].size();i++){
13         int vv =G[u][i];
14         if(vv==f)continue;
15         x+=max(dfs(vv,u),0LL);
16     }
17     ans=max(ans,x);
18     return x;
19 }
20 ll dFs(int u,int f){
21     ll x=v[u];
22     for(int i=0;i<G[u].size();i++){
23         int vv =G[u][i];
24         if(vv==f)continue;
25         x+=max(dFs(vv,u),0LL);
26     }
27     if(ans!=x)return x;
28     k++;
29     return 0;
30 }
31 int main(){
32     scanf("%d",&n);
33     for(int i=1;i<=n;i++)scanf("%lld",&v[i]);
34     for(int i=1;i<=n-1;i++){
35         int a,b;
36         scanf("%d%d",&a,&b);
37         G[a].push_back(b);
38         G[b].push_back(a);
39     }
40     dfs(1,0);
41     dFs(1,0);
42     cout<<ans*k<<" "<<k<<endl;
43     return 0;
44 }
View Code

F. Ehab and a weird weight formula

首先 一个结论 当以最小值为根时 节点越往下a越大 否则与除最小值节点外,每个节点必有一个值比它小矛盾。

然后来看一下每条边的贡献为 au+av+log2(dist(u,v))min(au,av)

考虑下最小生成树算法 再根据结论 对于每个非根节点

如果新图中u和v相连(au>av) 但v不是u的祖先 那么u与u和v的祖先相连明显更优

所以找它到祖先中贡献最小的边加进去就是答案

那么只要快速找到就ok了 av和au很好找 就是快速找祖先了

log2(dist(u,v))⌉和u相同时 min(au,av)越小越好  由结论可以看到v越靠近根越好

所以只要维护u的2的k次方祖先就可以了 最后再考虑下根和它相连的边

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 vector<int> G[500005];
 4 long long m=1,a[500005],dp[20][500005];
 5 long long ans;
 6 void dfs(int u,int f)
 7 {
 8     dp[0][u]=f;
 9     int d;
10     for(d=1;d<20&&dp[d-1][u]!=0;d++)
11         dp[d][u]=dp[d-1][dp[d-1][u]];
12     long long mn=d*a[m]+a[u];
13     for(d=0;d<20&&dp[d][u]!=0;d++)
14     mn=min(mn,(d+1)*a[dp[d][u]]+a[u]);
15     if (f!=0)
16         ans+=mn;
17     for(int i=0;i<G[u].size();i++)
18         if(G[u][i]!=f)
19             dfs(G[u][i],u);
20 }
21 int main()
22 {
23     int n;
24     scanf("%d",&n);
25     for (int i=1;i<=n;i++)
26     {
27         scanf("%lld",&a[i]);
28         if (a[i]<a[m])
29         m=i;
30     }
31     for (int i=1;i<n;i++)
32     {
33         int a,b;
34         scanf("%d%d",&a,&b);
35         G[a].push_back(b);
36         G[b].push_back(a);
37     }
38     dfs(m,0);
39     printf("%lld",ans);
40     return 0;
41 }
View Code

 

posted @ 2018-12-05 21:04  hermit-lei  阅读(145)  评论(0)    收藏  举报