【codeforces】【比赛题解】#862 CF Round #435 (Div.2)

这次比赛打得很舒服,莫名得了个Rank41,涨了219的Rating,就比较优秀。不过还是没有闫神厉害啊。
题目链接::P

【A】MEX

题意:

Evil博士把Mahmoud和Ehab绑架到了邪恶之地,因为他们在邪恶信息学奥林匹克竞赛(EOI)中取得了优异的成绩。博士想让他们回答一些问题后才放他们走。
Evil博士对集合很感兴趣,他有一个n个非负整数的集合。如果一个集合的MEX正好等于x,那么博士认为这个集合是邪恶的。
一个非负整数集合的MEX就是最小的不属于集合的非负整数。
Evil博士想要让他的集合变得邪恶,他每次可以做一个操作:往集合中添加一个非负整数或删除集合中的某个元素。
他最少做几次操作在能让这个集合变得邪恶呢?

输入:

第一行,两个数\(n,x(1\leq n\leq100,0\leq x\leq100)\)。
第二行,\(n\)个非负整数\(a_{1},a_{2},\cdots,a_{n}\),表示集合中的元素\((0\leq a_{i}\leq100)\)。

输出:

一个数,表示最小操作数。

题解:

添加所有不在集合中的小于\(x\)的非负整数,如果\(x\)在集合中,删除\(x\)。

 1 #include<cstdio>
 2 int n,x,a[1001],less,ans;
 3 int main(){
 4     scanf("%d%d",&n,&x);
 5     for(int i=1;i<=n;++i){
 6         scanf("%d",a+i);
 7         if(a[i]<x) ++less;
 8         if(a[i]==x) ++ans;
 9     }
10     printf("%d",ans+x-less);
11     return 0;
12 }

【B】二分图

题意:

Mahmoud和Ehab继续他们的旅程!在邪恶之地,众人皆知,Evil博士很喜欢二分图,特别是树。
Evil博士给定了一棵树,他想在树中加入尽量多条边,使得新图还是二分图。
求出最多添加的边数。

输入:

第一行,一个数\(n(1\leq n\leq10^5)\),表示树的顶点数。
接下来\(n-1\)行,每行两个数\(u_i,v_i(1\leq u_i,v_i\leq n)\),表示\(u_i,v_i\)间有连边。

输出:

一个整数,表示最多添加的边数。

题解:

黑白染色,答案=黑色点*白色点-(n-1)。

 1 #include<cstdio>
 2 int n,h[100001],nxt[200001],to[200001],tot=0,vis[100001],sums[2];
 3 inline void ins(int x,int y){nxt[++tot]=h[x];to[tot]=y;h[x]=tot;}
 4 void dfs(int u,int t){
 5     vis[u]=1;
 6     ++sums[t];
 7     for(int i=h[u];i;i=nxt[i]){
 8         if(!vis[to[i]]){
 9             dfs(to[i],t^1);
10         }
11     }
12 }
13 int main(){
14     int x,y;
15     scanf("%d",&n);
16     for(int i=1;i<n;++i) scanf("%d%d",&x,&y), ins(x,y), ins(y,x);
17     dfs(1,0);
18     printf("%I64d",1ll*sums[0]*sums[1]-n+1);
19     return 0;
20 }

【C】异或

题意:

Mahmoud和Ehab到达了第三站。你知道,Evil博士喜欢集合,不过这次,Evil博士不会展出任何他的集合,而是让他们创造一个新的集合,丰富自己的集合收藏。
Evil博士有着他喜欢的邪恶数字\(x\),他想让你创造一个包含\(n\)个不同的非负整数集合,使得这其中的数的异或和恰好等于\(x\)。集合中的数不大于\(10^6\)。

输入:

两个数,\(n,x(1\leq n\leq10^5,0\leq x\leq10^5)\)。

输出:

如果能创造这样的集合,先输出YES,然后输出一行\(n\)个互不相同的非负整数,表示集合,这些数不应该超过\(10^6\)。如果不能,输出NO。

题解:

当\(n=1\)时,输出\(x\)即可。
当\(n=2\)时,若\(x=0\),无解;否则输出\(0\;x\)。
当\(n=3\)时,若\(x=0\),输出\(1\;2\;3\);当\(x=1\),输出\(0\;2\;3\);当\(x>1\),输出\(0\;1\;x\oplus1\)。
当\(n>3\)时,先输出前\(n-3\)个非负整数,计算剩余的数,记为\(x_0\)。
接下来当做\(n=3\)的情况,不过输出的数要分别加上\(2^{17},2^{18},2^{17}+2^{18}\)。

 1 #include<cstdio>
 2 int a,b;
 3 int main(){
 4     scanf("%d%d",&a,&b);
 5     if(a==2&&b==0) {puts("NO"); return 0;}
 6     puts("YES");
 7     if(a==1) {printf("%d",b); return 0;}
 8     if(a==2) {printf("0 %d",b); return 0;}
 9     if(a==3) {if(b==0) printf("1 2 3"); else if(b==1) printf("0 2 3"); else printf("0 1 %d",b^1); return 0;}
10     for(int i=1;i<=a-3;++i){
11         printf("%d ",i); b^=i;
12     }
13     if(b==0) printf("%d %d %d",1+((1<<17)+(1<<18)),2+(1<<17),3+(1<<18));
14     else if(b==1) printf("%d %d %d",(1<<17)+(1<<18),2+(1<<17),3+(1<<18));
15     else printf("%d %d %d",(1<<17)+(1<<18),1+(1<<17),(b^1)+(1<<18));
16     return 0;
17 }

【D】01字串

交互题不会做XD。

【E】函数

题意:

Evil博士对数学和函数很感兴趣。
他给出了两个数组\(a_{1},\cdots,a_{n}\)和\(b_{1},\cdots,b_{m}(m\geq n)\)。
他又对满足\(0\leq j\leq m-n\)的\(j\)定义\(c_{i}=a_{i}-b_{i+j}\)和函数\(f(j)=|c_{1}-c_{2}+c_{3}-c_{4}\cdots c_{n}|\)。
也就是\(f(j)=|\sum_{i=1}^{n}(-1)^{i-1}*(a_{i}-b_{i+j})|\)。

Evil博士想要Mahmoud和Ehab去计算\(f(j)\)的最小值。他发现这太简单了。
于是他加入了\(q\)个操作,第\(i\)个操作对\(a\)数组中的\([l_i,r_i]\)段加上一个数\(x_i\)。然后再让他们计算这个函数的最小值。

题解:

简化算式:\(f(j)=|\sum_{i=1}^{n}(-1)^{i-1}*a_{i}+\sum_{i=1}^{n}(-1)^{i-1}*b_{i+j}|\)。
记第一个\(\sum\)的结果为\(Sum\)。记第二个\(\sum\)的结果为\(S_{j}\)。那么在操作间,\(Sum\)的值会改变。
改变的数值容易计算,可发现,这样交错相加减的算式,\(Sum\)这样变化:\(Sum \to Sum+x_{i}(r_{i}mod\:2-(l_{i}-1)mod\:2)\)。

而对于\(S_j\)的值,因为被绝对值包着,我们需要让\(S_j\)尽量接近\(-Sum\)。
因为\(b\)数组不会改变,故\(S_j\)也不会改变,将\(S_j\)排序后,二分查找即可。

 1 #include<cstdio>
 2 #include<algorithm>
 3 const int INF=99999999999999999ll;
 4 int n,m,q,mj;
 5 long long a[100011],b[100011],c[100011],sum;
 6 long long Abs(long long x){return x<0?-x:x;}
 7 int main(){
 8     scanf("%d%d%d",&n,&m,&q); mj=m-n;
 9     for(int i=1,f=1;i<=n;++i,f^=1) scanf("%I64d",a+i),sum+=f?a[i]:-a[i];
10     for(int i=1;i<=m;++i) scanf("%I64d",b+i);
11     for(int i=1,f=0;i<=n;++i,f^=1) c[0]+=f?b[i]:-b[i];
12     for(int i=1;i<=mj;++i) c[i]=-c[i-1]-b[i]+((n&1)?-b[i+n]:b[i+n]);
13     std::sort(c,c+mj+1);
14     int l,r,x,len,mid;
15     long long ans;
16     l=0, r=mj, ans=INF;
17     while(l<=r){
18         mid=(l+r)>>1;
19         if(c[mid]<-sum) l=mid+1;
20         else r=mid-1;
21         if(Abs(c[mid]+sum)<ans) ans=Abs(c[mid]+sum);
22     }
23     printf("%I64d\n",ans);
24     for(int i=1;i<=q;++i){
25         scanf("%d%d%d",&l,&r,&x);
26         len=r-l+1;
27         if(len&1) sum+=(l&1)?x:-x;
28         l=0, r=mj, ans=INF;
29         while(l<=r){
30             mid=(l+r)>>1;
31             if(c[mid]<-sum) l=mid+1;
32             else r=mid-1;
33             if(Abs(c[mid]+sum)<ans) ans=Abs(c[mid]+sum);
34         }
35         printf("%I64d\n",ans);
36     }
37     return 0;
38 }

 

posted @ 2017-10-19 22:49  粉兔  阅读(507)  评论(0编辑  收藏  举报