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 }
View Code

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 }
View Code

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 }
View Code

 

以上是关于Codeforces Round #530 (Div. 2)的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #530 (Div. 1)

Codeforces Round 530 大下分记

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))