Codeforces Round #569 (Div. 2)
A.Alex and a Rhombus
题意:求第n个图形的正方形个数
思路:答案为2*n*n-2*n+1
#include<iostream> #include<cstring> #include<cmath> #include<cstdlib> #include<cstdio> #include<algorithm> #include<string> #include<map> #include<queue> #include<vector> #include<stack> #define ll long long #define maxn 4001000 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; struct node{ int c,z,id; }p[301010]; bool cmp(node a,node b) { return a.c==b.c?a.z>b.z:a.c<b.c; } ll rd() { ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } void init() { int n=rd(); printf("%d\n",(n-1)*n/2*4+1); } void work() { } int main() { init(); work(); }
B. Nick and Array
题意:给你n个数字(-1e6<=ai<=1e6),每个数都可以变成-ai-1,问你怎么变换使得最后ai的乘积最大
思路1:分类讨论(烦)
讨论了很久结果是错误的,想把一些情况合并起来导致思考有问题,所以以后分类讨论就直接分类,不要合并,增加思维难度
找到一个最小值和最大值,之后根据他们是正数负数还是0分类考虑
#include<iostream> #include<cstring> #include<cmath> #include<cstdlib> #include<cstdio> #include<algorithm> #include<string> #include<map> #include<queue> #include<vector> #include<stack> #define ll long long #define maxn 4001000 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; struct node{ int c,x,id; }p[301010]; int a[201010],flag,fl[201010]; bool cmp(node a,node b) { return a.c<b.c; } ll rd() { ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } void init() { { int n=rd(),flg=0,an1=1e8,id1,an2=-1e8,id2,x; rep(i,1,n) { a[i]=rd(); if(a[i]<0) x++; if(a[i]<=an1) { an1=a[i]; id1=i; } if(a[i]>an2) { an2=a[i]; id2=i; } } if(n==1) { if(a[1]<0) printf("%d\n",-a[1]-1); else printf("%d\n",a[1]); return; } //printf("%d %d\n",id1,id2); if(x==0||x==n) ; x--; if(n%2==0) { if(a[id1]<0&&a[id2]<0) { } else{ if(a[id1]<0&&a[id2]>=0) { a[id2]=-a[id2]-1; } else if(a[id1]==0) { a[id1]=-a[id1]-1; a[id2]=-a[id2]-1; } else{ a[id1]=-a[id1]-1; a[id2]=-a[id2]-1; } } } else{ if(a[id1]<0&&a[id2]<0) { a[id1]=-a[id1]-1; } else{ if(a[id1]<0&&a[id2]>=0) { if(a[id1]*a[id2]>(-a[id2]-1)*(-a[id1]-1)) { a[id2]=-a[id2]-1; a[id1]=-a[id1]-1; } } else if(a[id1]==0) { a[id1]=-a[id1]-1; } else{ a[id1]=-a[id1]-1; } } } rep(i,1,n) if(i==id1||i==id2) printf("%d ",a[i]); else if(a[i]>=0) printf("%d ",-a[i]-1); else printf("%d ",a[i]); printf("\n"); } } void work() { } int main() { init(); work(); } /* 4 -3 -3 2 2 4 -3 -3 -3 2 3 4 -3 2 3 -3 -3 2 2 -4 2 1 0 1 1 1 -2 5 0 1 2 0 -1 */
思路2:可以得出,正数和0都是操作之后会使积变大,直接反转,如果n是奇数,就找一个最小值反转(by DUP4)
#include <bits/stdc++.h> using namespace std; #define N 100010 int n, a[N]; int main() { while (scanf("%d", &n) != EOF) { for (int i = 1; i <= n; ++i) { scanf("%d", a + i); if (a[i] >= 0) { a[i] = -a[i] - 1; } } if (n & 1) { int Min = *min_element(a + 1, a + 1 + n); for (int i = 1; i <= n; ++i) { if (a[i] == Min) { a[i] = -a[i] - 1; break; } } } for (int i = 1; i <= n; ++i) { printf("%d%c", a[i], " \n"[i == n]); } } return 0; }
C. Valeriy and Deque
题意:n个数,m次询问,询问第k次操作是第一个数和第二个数是什么,一次操作:将前两个数字的较大者放入队头,将较小者放入队尾。
思路,经过n次操作之后,第一个数必定是最大值,第二个数是一个循环。注意全局变量和局部变量(编译器有毒,好吧使自己太菜了,z没有初始化)
#include<iostream> #include<cstring> #include<cmath> #include<cstdlib> #include<cstdio> #include<algorithm> #include<string> #include<map> #include<queue> #include<vector> #include<stack> #define ll long long #define maxn 4001000 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; struct node{ int x,y; }q[1001010]; int a[1001010],len,p=0; ll rd() { ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } void init() { int n,m,an,z; n=rd();m=rd();an; rep(i,1,n) { a[i]=rd(); z=max(z,a[i]); } rep(i,1,3*n) { int x1=a[i],x2=a[i+1]; a[i+1]=max(x1,x2); a[i+n]=min(x1,x2); q[++len].x=x1; q[len].y=x2; if(z==a[i+1]) { p++; if(p==2) { an=i; } } } //printf("%d\n",an); while(m--) { ll s=rd(); if(s<=2*n) { printf("%d %d\n",q[s].x,q[s].y); } else{ printf("%d %d\n",q[(s-an)%(n-1)+an].x,q[(s-an)%(n-1)+an].y); //else printf("%d %d\n",q[3*n].x,q[3*n].y); } } } void work() { } int main() { init(); work(); }
#include<iostream> #include<cstring> #include<cmath> #include<cstdlib> #include<cstdio> #include<algorithm> #include<string> #include<map> #include<queue> #include<vector> #include<stack> #define ll long long #define maxn 4001000 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; struct node{ int x,y; }q[1001010]; int a[1001010],len,p=0; int n,m,an,z; ll rd() { ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } void init() { n=rd();m=rd();an; rep(i,1,n) { a[i]=rd(); z=max(z,a[i]); } rep(i,1,3*n) { int x1=a[i],x2=a[i+1]; a[i+1]=max(x1,x2); a[i+n]=min(x1,x2); q[++len].x=x1; q[len].y=x2; if(z==a[i+1]) { p++; if(p==2) { an=i; } } } //printf("%d\n",an); while(m--) { ll s=rd(); if(s<=3*n) { printf("%d %d\n",q[s].x,q[s].y); } else{ printf("%d %d\n",q[(s-an)%(n-1)+an].x,q[(s-an)%(n-1)+an].y); //else printf("%d %d\n",q[3*n].x,q[3*n].y); } } } void work() { } int main() { init(); work(); }
D. Tolik and His Uncle
题意:从(1,1)开始走完(n*m)地图的每一个点,使得前后两个点形成的向量没有重复,输出路径。
思路:当为1*n的地图时 (1,1)->(1,n) ->(1,2) ->(1,n-1) ->...
如果为n*m的地图呢,(1,1)->(n,m) ->(1,2) ->(n,m-1) ->...
#include<bits\stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; int n,m,a[1010100],b[1010100]; int pos1=1,pos2=1,z1=0,z2=0; int main() { scanf("%d%d",&n,&m); rep(i,1,n/2) { rep(j,1,m) { printf("%d %d\n",i,j); printf("%d %d\n",n+1-i,m+1-j); } } if(n%2==1) { printf("%d %d\n",n/2+1,1); a[1]=1; rep(i,2,m) { if(i%2==0) a[i]=m+1-a[i-1]; else a[i]=m+2-a[i-1]; printf("%d %d\n",n/2+1,a[i]); } } }
E. Serge and Dining Room
题意:有n种菜,和m个人,每个人会买他能支付的一个最贵的菜。
q个询问:
1.可以改变一个菜的价格,问你m个人过后最贵的菜是多少钱。
2.可以改变一个人有的钱,问你m个人过后最贵的菜是多少钱。
思路:线段树
如果是一个菜,使区间(1,c[i])都加1
如果是一个人,使区间(1,c[i])都减1,
查询单点>0,最右边的值。
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; #define ll long long const int N=3e5+5; int a[N],b[N],t[N],v[3*N],p[N],x[N]; int ad[N*10],tree[N*10]; int n,m,q,sum; ll rd() { ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } void init() { n=rd();m=rd();sum=0; rep(i,1,n) a[i]=rd(),v[++sum]=a[i]; rep(i,1,m) b[i]=rd(),v[++sum]=b[i]; q=rd(); rep(i,1,q) { t[i]=rd(); if(t[i]<=2) { p[i]=rd(),x[i]=rd(),v[++sum]=x[i]; } } sort(v+1,v+1+sum); sum = unique(v+1, v + sum+1) - v-1; rep(i,1,n) a[i] = lower_bound(v+1,v + sum+1,a[i]) -v; rep(i,1,m) b[i] = lower_bound(v+1,v + sum+1,b[i]) -v; rep(i,1,q) if(t[i]<=2) x[i] = lower_bound(v+1,v + sum+1,x[i]) -v; //rep(i,1,sum) printf(" %d\n",v[i]); } void down(int rt) { ad[rt*2]+=ad[rt]; ad[rt*2+1]+=ad[rt]; tree[rt*2]+=ad[rt]; tree[rt*2+1]+=ad[rt]; ad[rt]=0; } void upd(int rt,int L,int R,int l,int r,int x) { if(l>R || r<L) return; if(l<=L&&R<=r) { tree[rt]+=x; ad[rt]+=x; return; } int mid=(L+R)/2; down(rt); upd(rt*2,L,mid,l,r,x); upd(rt*2+1,mid+1,R,l,r,x); tree[rt]=max(tree[rt*2],tree[rt*2+1]); } void add(int x) { upd(1,1,sum,0,x,1); } void del(int x) { upd(1,1,sum,0,x,-1); } int getit(int rt,int l,int r) { if(l==r) return l; int m=(l+r)/2; down(rt); if(tree[2*rt+1]>0) return getit(2*rt+1,m+1,r); else return getit(2*rt,l,m); } int get() { if(tree[1]>=1) return v[getit(1,1,sum)]; else return -1; } void work() { rep(i,1,n) add(a[i]); rep(i,1,m) del(b[i]); rep(i,1,q) { if(t[i]==1) { del(a[p[i]]); a[p[i]]=x[i]; add(x[i]); } if(t[i]==2) { add(b[p[i]]); b[p[i]]=x[i]; del(x[i]); } printf("%d\n",get()); } } int main() { init(); work(); //outit(); }