当前鸽掉没补完的题解,为了能复制还是先发出来吧哈哈
Problem C
解题思路:
按照题意暴力的做,记得对于操作2,找到终点时压缩一下路径。
代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<cmath> #define ll long long using namespace std; const int N = 1e5+5; int n,m,t,x,y; int lzq[N]; int cao[N],pos[N]; int main() { int t; scanf("%d",&t); while (t--){ int n,m; scanf("%d %d",&n,&m); memset(lzq,0,sizeof lzq); for (int i=1;i<=m;i++){ scanf("%d %d",cao+i,pos+i); if (cao[i]==1){ lzq[pos[i]]++; } else { int p = pos[i]; while (cao[p]!=1) p = pos[p]; pos[i] = p; lzq[pos[p]]++; } } for (int i=1;i<=n;i++) if (i==1) printf("%d",lzq[i]); else printf(" %d",lzq[i]); printf("\n"); } return 0; }
Problem E
解题思路:
注意是环
当个数为1,2的时候,A胜利;
否则,A将串断开后,B可以一次取走所有,或者根据情况取一个或者两个,使得剩下的两堆相同,然后只要模仿A的行动就可以了,最后B一定胜利。
代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<cmath> #define ll long long using namespace std; const int N = 1e5+5; int n,m,t,x,y; int main() { ll n; while (~scanf("%lld",&n)){ if (n==1||n==2) printf("A\n"); else printf("B\n"); } return 0; }Problem H
解题思路:
个数等于a/gcd(a,b)*b/gcd(a,b)
代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<cmath> #define ll long long using namespace std; const int N = 1e5+5; int n,m,t,x,y; ll gcd(ll a,ll b){ return (a-a/b*b)==0? b:gcd(b,a-a/b*b); } int main() { ll a,b; while (~scanf("%lld %lld",&a,&b)){ if (a==b) { printf("1\n"); continue; } ll sb = gcd(a,b); a = a/sb; b = b/sb; printf("%lld\n",a*b); } return 0; }Problem H
解题思路:
后缀数组模板题。
后缀数组构造的时候需要s[n] = 0,然后构造n+1,不然越界。
#include<cstdio>8 #include<cstring> #include<algorithm> #define lson rt<<1,l,m #define rson rt<<1|1,m+1,r #define mid int m=l+r>>1 #define tl tree[rt<<1] #define tr tree[rt<<1|1] #define debug(x) printf("----Line %s----\n",#x) #define inf 0x3f3f3f3f using namespace std; const int N = 2e5+5; int wa[N],wb[N],cnt[N<<1],sa[N],rnk[N],height[N]; int tree[N<<2],ans; char s[N]; void push_up(int rt) { tree[rt] = min(tl,tr); } void build(int rt,int l,int r)///线段树维护height[1]~height[n-1] (不会RMQ) { if (l==r){ tree[rt] = height[l]; return ; } mid; build(lson); build(rson); push_up(rt); } void query(int L,int R,int rt,int l,int r)///查找L~R的最小值 { if (L<=l && r<=R){ ans = min(ans,tree[rt]); return ; } mid; if (L<=m) query(L,R,lson); if (R>m) query(L,R,rson); } void sufbuild(int n,int m)///构造后缀数组 { int p,i,j,*x=wa,*y=wb; for (i=0;i<m;i++) cnt[i] = 0; for (i=0;i<n;i++) cnt[x[i]=s[i]]++; for (i=1;i<m;i++) cnt[i] += cnt[i-1]; for (i=n-1;i>=0;i--) sa[--cnt[x[i]]] = i; for (j=1,p=1;p<n;j<<=1,m=p){//debug("喵喵喵"); for (p=0,i=n-j;i<n;i++) y[p++] = i/*,printf("y[%d]=%d\n",p-1,y[p-1])*/; for (i=0;i<n;i++) if (sa[i]>=j) y[p++] = sa[i]-j; //debug("汪汪汪"); for (i=0;i<m;i++) cnt[i] = 0;//debug("汪"); for (i=0;i<n;i++) /*printf("y[%d]=%d,x[y[%d]]=%d\n",i,y[i],i,x[y[i]]),*/cnt[x[y[i]]]++;//debug("吐"); for (i=1;i<m;i++) cnt[i] += cnt[i-1];//debug("碎"); for (i=n-1;i>=0;i--) sa[--cnt[x[y[i]]]] = y[i];//debug("佛"); //debug("fuckfuckfuck"); swap(x,y); x[sa[0]] = 0; p = 1; for (i=1;i<n;i++) x[sa[i]] = ( y[sa[i]]==y[sa[i-1]] && y[sa[i]+j]==y[sa[i-1]+j] )? p-1:p++; } } void getheight(int n) { int k=0; for (int i=0;i<n;i++) rnk[sa[i]] = i; for (int i=0;i<n;i++){ if (rnk[i]==0){ height[rnk[i]] = k = 0; continue; } if (k) k--; int j = sa[rnk[i]-1]; while (i+k<n && j+k<n && s[i+k]==s[j+k]) k++; height[rnk[i]] = k; } } int main() { int n; scanf("%d",&n); scanf("%s",s);//debug(0); s[n]=0; sufbuild(n+1,256);//debug(1); getheight(n+1);//debug(2); build(1,1,n);///维护height[1]~height[n] /* printf("\n"); for (int i=0;i<n;i++) printf("%s\n",s+sa[i]); for (int i=0;i<n;i++) printf("rank[%d]=%d\n",i,rnk[i]); for (int i=0;i<n;i++) printf("height[%d]=%d\n",i,height[i]); */ int q; scanf("%d",&q); while (q--){ int l,r,ll,rr; scanf("%d %d %d %d",&l,&r,&ll,&rr); int L=rnk[l],R=rnk[ll]; if (L==R){///两者起点相同,特殊处理 printf("%d\n",min(r-l+1,rr-ll+1)); continue; } if (L>R) swap(L,R); L++; ans = inf; query(L,R,1,1,n); printf("%d\n",min(ans,min(r-l+1,rr-ll+1))); } return 0; }