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 }
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 }
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 }
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 }
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 }
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 }
                    
                
                
            
        
浙公网安备 33010602011771号