Codeforces Round #530 (Div. 2)
Posted lqllulu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #530 (Div. 2)相关的知识,希望对你有一定的参考价值。
B:Squares and Segments
题意:
给定n,求最小的a+b使得a*b>=n
题解:
直接开平方最优。
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #include <iostream> 5 #include <cmath> 6 7 using namespace std; 8 9 int main(){ 10 int n; 11 scanf("%d",&n); 12 int m=sqrt(n); 13 int m2=n/m; 14 if(m>m2)swap(m,m2); 15 if(m*m2<n){ 16 m2++; 17 } 18 printf("%d ",m+m2); 19 return 0; 20 }
C. Postcard
按照题意模拟一下就行。
D. Sum in the tree
题意:
Mitya有一个n个结点的有根树,结点编号从1到n,根结点编号为1。每个结点有一个权值av>=0,对于每个点v,Mitya要计算si值,si的定义是从v点到根结点的av的和。现在Mitya删除了所有的av,然后删除了偶数层的的sv,你要给每个结点构造出av,使得av的和最小。
题解:
贪心,偶数层s[u]全是—1,那么a[u]=min(s[v]),v是u的孩子结点。
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #include <iostream> 5 #include <vector> 6 7 using namespace std; 8 typedef long long LL; 9 const int maxn=1e5+10; 10 const LL INF=1e18; 11 int n; 12 int fa[maxn]; 13 LL s[maxn],a[maxn]; 14 vector<int>G[maxn]; 15 bool dfs(int u,int Fa,LL sum){ 16 if(s[u]!=-1){ 17 if(sum>s[u])return false; 18 a[u]=s[u]-sum; 19 for(int i=0;i<G[u].size();i++){ 20 int v=G[u][i]; 21 if(v==Fa)continue; 22 if(!dfs(v,u,sum+a[u])) 23 return false; 24 } 25 }else{ 26 LL Min=INF; 27 for(int i=0;i<G[u].size();i++){ 28 int v=G[u][i]; 29 if(v==Fa)continue; 30 Min=min(Min,s[v]); 31 } 32 if(Min<sum)return false; 33 if(Min<INF) 34 a[u]=Min-sum; 35 for(int i=0;i<G[u].size();i++){ 36 int v=G[u][i]; 37 if(v==Fa)continue; 38 if(!dfs(v,u,sum+a[u])) 39 return false; 40 } 41 } 42 return true; 43 } 44 int main(){ 45 scanf("%d",&n); 46 for(int i=2;i<=n;i++){ 47 scanf("%d",&fa[i]); 48 G[fa[i]].push_back(i); 49 G[i].push_back(fa[i]); 50 } 51 for(int i=1;i<=n;i++) 52 scanf("%I64d",&s[i]); 53 if(!dfs(1,-1,0)){ 54 printf("-1 "); 55 return 0; 56 } 57 58 LL sum=0; 59 for(int i=1;i<=n;i++){ 60 // printf("%d ",a[i]); 61 sum+=a[i]; 62 } 63 64 printf("%I64d ",sum); 65 return 0; 66 }
E. Nice table
题意:
题意 有一个nm的表格,包括‘A‘,‘G‘,‘C‘,‘T‘.四个字母。我们称一个表格为good当每一个22的格子都包括这四个不同的字母。你的任务是找到一个good表格,与给出的表格不同的字母数最少。
题解:
我们发现能组成good的表格只有可能是每一列两两重复,或者每一行两辆重复,情况并不多 若是行的,那么第一行两个的概率是C(4,2)=6,然后两个不同的排列是2,第二行不同排列的方案是2,一共有622=24种情况,列的也是这样,于是一共有224=48种情况。每种情况扫一遍计数的复杂度是300000,那么如果枚举每种情况然后计数的话是48300000=14400000=1.44*10^7。
代码暂时留坑。
F. Cookies
题意:
M和V在玩一个游戏,他们有一个有n个结点的有根树,结点的编号从1到n,根的编号为1。每个节点都有一些饼干,第i个结点有xi个饼干,M在i结点吃一块饼干花费的时间是ti。有一颗棋子,开始的时候在树的根结点,它可以花费li的时间走结点i到它父结点的边。M执先手。 M可以把棋子移动到当前结点的孩子结点。V可以删除棋子所在结点到它孩子结点的一条边。 M可以在任何时候停止这个游戏,一旦他停止这个游戏,他可以将棋子移动到根结点,并吃一些路上的饼干,要求总的时间不超过T。要求你求M可以吃最多的饼干数目。
题解:
如果已经确定在结点v结束,那么能吃的最多的饼干数是多少?路径上花费的时间是tv,那么吃饼干的时间就是T-tv,那么就显然是吃花费时间最少的那些饼干。这个操作显然可以用线段树进行维护。所以现在我们已经求出了c[i]为以i为结束结点,能吃最多的饼干数。然后我们进行dp。设dp[u]为在以u结点为根的子树中选择一个结束结点能吃的最多的饼干数目。转移就是dp[u]=max(c[u],dp[v]);其中v是u的所有子结点中dp[v]值第二大的(因为博弈)。
1 #include <cstdio> 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 #include <vector> 6 7 using namespace std; 8 typedef long long LL; 9 const int maxn=1e6+10; 10 int n; 11 LL T,Max; 12 LL x[maxn],t[maxn]; 13 int head[maxn],Next[2*maxn],to[2*maxn],w[2*maxn]; 14 LL ans[maxn],Max_ans[maxn]; 15 int sz; 16 void init(){ 17 sz=0; 18 memset(head,-1,sizeof(head)); 19 } 20 void add_edge(int a,int b,int c){ 21 ++sz; 22 to[sz]=b;w[sz]=c;Next[sz]=head[a];head[a]=sz; 23 } 24 LL numv[4*maxn],sumv[4*maxn]; 25 void maintain(int o){ 26 int lc=2*o,rc=2*o+1; 27 sumv[o]=sumv[lc]+sumv[rc]; 28 numv[o]=numv[lc]+numv[rc]; 29 } 30 31 void update(int o,int L,int R,int p,int v){ 32 if(L==R){ 33 if(v<0){ 34 v=-v; 35 numv[o]-=x[v]; 36 sumv[o]-=x[v]*t[v]; 37 }else{ 38 numv[o]+=x[v]; 39 sumv[o]+=x[v]*t[v]; 40 } 41 return ; 42 } 43 int M=L+(R-L)/2; 44 if(p<=M) 45 update(2*o,L,M,p,v); 46 else 47 update(2*o+1,M+1,R,p,v); 48 maintain(o); 49 } 50 LL query(int o,int L,int R,LL res){ 51 if(res==0||numv[o]==0) 52 return 0; 53 if(res>=sumv[o]) 54 return numv[o]; 55 if(L==R){ 56 LL num=sumv[o]/numv[o]; 57 return res/num; 58 } 59 int M=L+(R-L)/2; 60 int lc=2*o,rc=2*o+1; 61 LL _res=query(lc,L,M,res); 62 if(sumv[lc]<res) 63 _res+=query(rc,M+1,R,res-sumv[lc]); 64 return _res; 65 } 66 67 LL dfs(int u,int fa,LL sum){ 68 if(sum==0)return 0; 69 update(1,1,Max,t[u],u); 70 ans[u]=query(1,1,Max,sum); 71 Max_ans[u]=ans[u]; 72 for(int i=head[u];i!=-1;i=Next[i]){ 73 int v=to[i]; 74 if(v==fa)continue; 75 Max_ans[u]=max(Max_ans[u],dfs(v,u,sum-2*w[i])); 76 } 77 update(1,1,Max,t[u],-u); 78 return Max_ans[u]; 79 } 80 LL ANS; 81 LL dp[maxn]; 82 void solve(int u,int fa){ 83 dp[u]=ans[u]; 84 int Max=0,Max_i=0; 85 for(int i=head[u];i!=-1;i=Next[i]){ 86 int v=to[i]; 87 if(v==fa)continue; 88 solve(v,u); 89 if(dp[v]>Max){ 90 Max=dp[v]; 91 Max_i=v; 92 } 93 } 94 for(int i=head[u];i!=-1;i=Next[i]){ 95 int v=to[i]; 96 if(v==fa||v==Max_i)continue; 97 dp[u]=max(dp[u],dp[v]); 98 } 99 } 100 101 102 int main(){ 103 scanf("%d%I64d",&n,&T); 104 for(int i=1;i<=n;i++) 105 scanf("%I64d",&x[i]); 106 for(int i=1;i<=n;i++){ 107 scanf("%I64d",&t[i]); 108 Max=max(Max,t[i]); 109 } 110 init(); 111 for(int i=2;i<=n;i++){ 112 int p,w; 113 scanf("%d%d",&p,&w); 114 add_edge(i,p,w); 115 add_edge(p,i,w); 116 } 117 dfs(1,0,T); 118 ANS=ans[1]; 119 int Max=0,Mt=0; 120 for(int i=head[1];i!=-1;i=Next[i]){ 121 int v=to[i]; 122 solve(v,1); 123 ANS=max(ANS,dp[v]); 124 } 125 printf("%I64d ",ANS); 126 return 0; 127 }
以上是关于Codeforces Round #530 (Div. 2)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #530 (Div. 1)
Codeforces Round #530 (Div. 2)
Codeforces Round #530 (Div. 2) (前三题题解)
Codeforces Round #530 (Div. 2)F Cookies (树形dp+线段树)
Codeforces 1099 D. Sum in the tree-构造最小点权和有根树 贪心+DFS(Codeforces Round #530 (Div. 2))