Codeforces Global Round 3

A.2c+2min(a,b)+(a!=b)

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 6 typedef long long ll;
 7 using namespace std;
 8 
 9 int a,b,c;
10 
11 int main(){
12     cin>>a>>b>>c;
13     cout<<2ll*c+2ll*min(a,b)+(abs(b-a)>=1)<<endl;
14     return 0;
15 }
View Code

B.必定是删除一些第一部分航班之后删除一些紧接着的第二部分航班,枚举第一部分删多少个,two-pointers。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 5 using namespace std;
 6 
 7 const int N=200010;
 8 int n,m,k,ta,tb,a[N],b[N];
 9 
10 int main(){
11     scanf("%d%d%d%d%d",&n,&m,&ta,&tb,&k);
12     rep(i,1,n) scanf("%d",&a[i]);
13     rep(i,1,m) scanf("%d",&b[i]);
14     if (k>=min(n,m)){ printf("-1
"); return 0; }
15     int now=1,ans=0;
16     rep(i,1,n){
17         if (i-1>k) break;
18         while (a[i]+ta>b[now] && now<=m) now++;
19         int rest=k-(i-1);
20         if (now+rest>m){ ans=-1; break; }
21         ans=max(ans,b[now+rest]+tb);
22     }
23     printf("%d
",ans);
24     return 0;
25 }
View Code

C.找到每个数应该在的位置并想办法在5次之内把它放到那里去。做法很多,具体见代码。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 6 typedef long long ll;
 7 using namespace std;
 8 
 9 const int N=3000010;
10 int n,tot,a[N],id[N],p[N];
11 struct P{ int a,b; }q[N];
12 
13 bool cmp(int x,int y){ return a[x]<a[y]; }
14 
15 void work(int x,int y){ q[++tot]=(P){x,y}; swap(p[x],p[y]); swap(id[p[x]],id[p[y]]); }
16 
17 void Swap(int x,int y){
18     if (x>y) swap(x,y);
19     if (y-x>=n/2) { work(x,y); return; }
20     if (x<=n/2){
21         if (y<=n/2) work(x,n),work(y,n),work(x,n); else work(x,n),work(n,1),work(1,y),work(1,n),work(n,x);
22     }else work(x,1),work(1,y),work(x,1);
23 }
24 
25 int main(){
26     scanf("%d",&n);
27     rep(i,1,n) scanf("%d",&a[i]),id[i]=i;
28     sort(id+1,id+n+1,cmp);
29     rep(i,1,n) p[id[i]]=i;
30     rep(i,1,n) if (id[i]!=i) Swap(id[i],i);
31     printf("%d
",tot);
32     rep(i,1,tot) printf("%d %d
",q[i].a,q[i].b);
33     return 0;
34 }
View Code

D.答案就是max(ai<bi的数对数,ai>bi的数对数),因为当ai<bi时把ai从大到小排一定是一个合法解,ai>bi同理。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 6 typedef long long ll;
 7 using namespace std;
 8 
 9 const int N=300010;
10 int n,s1,s2,tot,q[N];
11 struct P{ int a,b; }p[N];
12 
13 bool cmp1(int a,int b){ return p[a].a<p[b].a; }
14 bool cmp2(int a,int b){ return p[a].a>p[b].a; }
15 
16 int main(){
17     scanf("%d",&n);
18     rep(i,1,n){
19         scanf("%d%d",&p[i].a,&p[i].b);
20         if (p[i].a>p[i].b) s1++; else s2++;
21     }
22     if (s1>s2){
23         rep(i,1,n) if (p[i].a>p[i].b) q[++tot]=i;
24         sort(q+1,q+tot+1,cmp1); printf("%d
",s1);
25         rep(i,1,tot) printf("%d ",q[i]);
26     }else{
27         rep(i,1,n) if (p[i].a<p[i].b) q[++tot]=i;
28         sort(q+1,q+tot+1,cmp2); printf("%d
",s2);
29         rep(i,1,tot) printf("%d ",q[i]);
30     }
31     return 0;
32 }
View Code

E.注意到无论怎么操作石子之间的相对位置都是不变的,于是每个t分别对应哪个s也是确定的。把石子分成两类,si<ti和si>ti,从左到右依次考虑每个第一类石子,找到它后面的最近的第二类石子来完成操作。若所有石子位移总和不为0或中间有某个第一类石子后面找不到第二类石子则必定无解。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 4 typedef long long ll;
 5 using namespace std;
 6 
 7 const int N=3000010;
 8 ll s1,s2;
 9 int n,n1,n2,num,t[N];
10 struct P{ int s,id; }a[N],a1[N],a2[N];
11 struct Q{ int x,y,d; }q[N];
12 bool operator <(const P &a,const P &b){ return a.s<b.s; }
13 
14 int main(){
15     scanf("%d",&n);
16     rep(i,1,n) scanf("%d",&a[i].s),s1+=a[i].s,a[i].id=i;
17     rep(i,1,n) scanf("%d",&t[i]),s2+=t[i];
18     if (s1!=s2){ puts("NO"); return 0; }
19     sort(a+1,a+n+1); sort(t+1,t+n+1);
20     rep(i,1,n){
21         if (a[i].s<t[i]) a1[++n1]=(P){t[i]-a[i].s,i};
22         if (a[i].s>t[i]) a2[++n2]=(P){a[i].s-t[i],i};
23     }
24     int j=1;
25     rep(i,1,n1){
26         int s=a1[i].s;
27         while (s){
28             if (a1[i].id>a2[j].id){ puts("NO"); return 0; }
29             if (s<a2[j].s) q[++num]=(Q){a[a1[i].id].id,a[a2[j].id].id,s},a2[j].s-=s,s=0;
30                 else q[++num]=(Q){a[a1[i].id].id,a[a2[j].id].id,a2[j].s},s-=a2[j].s,j++;
31         }
32     }
33     printf("YES
%d
",num);
34     rep(i,1,num) printf("%d %d %d
",q[i].x,q[i].y,q[i].d);
35     return 0;
36 }
View Code

F.考虑将每个数的贡献算到它的最低位1上去,那么我们要做的就是对于每一位让它的贡献与初始总和反号。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 5 typedef long long ll;
 6 using namespace std;
 7 
 8 const int N=300010;
 9 int n;
10 ll sm,ans,a[N],mk[N];
11 
12 int main(){
13     ios::sync_with_stdio(false);
14     cin>>n;
15     rep(i,1,n) cin>>a[i]>>mk[i],sm+=a[i];
16     if (sm<0) rep(i,1,n) a[i]=-a[i];
17     for (int i=62; ~i; i--){
18         sm=0;
19         rep(j,1,n) if (mk[j]==1ll<<i) sm+=a[j];
20         if (sm>0) ans|=1ll<<i;
21         rep(j,1,n) if (mk[j]&(1ll<<i)){
22             mk[j]^=1ll<<i;
23             if (sm>0) a[j]=-a[j];
24         }
25     }
26     cout<<ans<<endl;
27     return 0;
28 }
View Code
原文地址:https://www.cnblogs.com/HocRiser/p/10962566.html