7.10
CF380C Sereja and Brackets
题意:
给一个只有左右括号的序列和n段区间,求每个序列区间中最长的匹配括号子序列的长度。
思路:
线段树,记录每个区间中未匹配的左括号的未匹配的右括号的个数,寻找区间是都是从左往右找,最后答案就是区间长度-1-未匹配的左右括号个数
code:
#include<cstdio> #define N 1000000 using namespace std; struct arr{ int l,r,a,b; }tr[N*4]; int ri,le,n,l; char s[N]; void build(int w,int l,int r){ tr[w].l=l,tr[w].r=r; if (l==r){ if (s[l-1]=='(') tr[w].a++; else tr[w].b++; return; } int mid=(l+r)/2; build(w*2,l,mid); build(w*2+1,mid+1,r); tr[w].a=tr[w*2+1].a; tr[w].b=tr[w*2].b; if (tr[w*2].a>tr[w*2+1].b) tr[w].a+=(tr[w*2].a-tr[w*2+1].b); else tr[w].b+=(tr[w*2+1].b-tr[w*2].a); } void find(int w,int l,int r){ if (tr[w].l==l&&tr[w].r==r){ if (tr[w].b<=le) le-=tr[w].b; else ri+=tr[w].b-le,le=0; le+=tr[w].a; return; } int mid=(tr[w].l+tr[w].r)/2; if (r<=mid) find(w*2,l,r); else if (l>mid) find(w*2+1,l,r); else{ find(w*2,l,mid); find(w*2+1,mid+1,r); } } int main(){ scanf("%s",&s); for (l=0;s[l]!='\0';l++); build(1,1,l); scanf("%d",&n); for (int i=1;i<=n;i++){ int x,y; le=ri=0; scanf("%d%d",&x,&y); find(1,x,y); printf("%d\n",y-x+1-le-ri); } }
CF1366D Two Divisors
题意:
给出n个数字,判断每个数字a是否存在两个因数d1>1和d2>1,满足gcd(d1+d2,a)=1,没有则输出两个-1
思路:
每个数字都可以分成p1^k1*p2^k2*p3^k3... (p1<p2<p3...)
则a的因数有a/(p1^k1)和p1,则a/(p1^k1)+p1与p1,p2,p3任何一个都互质
code:
#include<cstdio> #include<algorithm> #define N 10000000 using namespace std; int s[N+7],n,a[N+7],b[N+7]; bool f[N+7]; int main(){ for (int i=1;i<=N;i++) s[i]=i; for (int i=2;i<=N;i++) if (!f[i]) for (int j=2;j<=N/i;j++){ f[i*j]=true; s[i*j]=min(s[i*j],i); } scanf("%d",&n); for (int i=1;i<=n;i++){ int x,y; scanf("%d",&x); y=x; a[i]=b[i]=1; while ((x%s[y])==0){ a[i]*=s[y]; x/=s[y]; } if (x==1) a[i]=b[i]=-1; else b[i]=x; } for (int i=1;i<=n;i++) printf("%d ",a[i]); printf("\n"); for (int i=1;i<=n;i++) printf("%d ",b[i]); }
CF1370D Odd-Even Subsequence
题意:
给出一个长度为n序列,你可以将序列删剩m个数字,使得奇数位置的最大值和偶数位置的最大值的最小值最小。
题意:
这种题目求最大值最小的可以考虑二分,判断能否简洁的取到m/2个不大于mid的值,还要考虑m的奇偶。
code:
#include<cstdio> #include<algorithm> #define N 200007 using namespace std; int n,m,ma,a[N],l,r,mid; bool check1(int x){ int p=0; if (m%2==1) for (int i=2;i<n;i++){ if (a[i]<=x) p++,i++; } else for (int i=2;i<=n;i++){ if (a[i]<=x) p++,i++; } if (p>=m/2) return true; return false; } bool check2(int x){ int p=0; if (m%2==1) for (int i=1;i<=n;i++){ if (a[i]<=x) p++,i++; } else for (int i=1;i<n;i++){ if (a[i]<=x) p++,i++; } if (p>=(m+1)/2) return true; return false; } int main(){ scanf("%d%d",&n,&m); for (int i=1;i<=n;i++){ scanf("%d",&a[i]); r=max(a[i],r); } l=1; while (l<r){ mid=(l+r)/2; if (check1(mid)||check2(mid)) r=mid; else l=mid+1; } printf("%d\n",l); }
CF2B The least round way
题意:
给出一个n*n个矩阵,从左上角走到右上角,求路线中所有数之积结尾0的个数最少的个数,并输出路线
题意:
结尾有0就是2*5,分别求2最少时min(2的个数,5的个数)和5最少时min(2的个数,5的个数),有一个特殊情况就是有0,如果有0且最终结果大于1,那就输出1,路线是要通过0的位置
code:
#include<cstdio> #include<algorithm> #include<cstring> #define N 1007 using namespace std; int n,a[N][N],h[N][N],t[N][N],p1[N][N],p2[N][N],c1[N][N],c2[N][N],ans; char d1[N][N],d2[N][N],p[N*2]; void check1(){ for (int i=1;i<=n;i++) for (int j=1;j<=n;j++){ int x1=p1[i-1][j],y1=p1[i][j-1]; int x2=c2[i-1][j],y2=c2[i][j-1]; if (i==1) x1=x2=0xffffff; if (j==1) y1=y2=0xffffff; if (x1<y1||(x1==y1)&&(p2[i-1][j]<=p2[i][j-1])) p1[i][j]=h[i][j]+p1[i-1][j],p2[i][j]=t[i][j]+p2[i-1][j],d1[i][j]='D'; else p1[i][j]=h[i][j]+p1[i][j-1],p2[i][j]=t[i][j]+p2[i][j-1],d1[i][j]='R'; if (x2<y2||(x2==y2)&&(c1[i-1][j]<=c1[i][j-1])) c1[i][j]=h[i][j]+c1[i-1][j],c2[i][j]=t[i][j]+c2[i-1][j],d2[i][j]='D'; else c1[i][j]=h[i][j]+c1[i][j-1],c2[i][j]=t[i][j]+c2[i][j-1],d2[i][j]='R'; } int k1=min(p1[n][n],p2[n][n]),k2=min(c1[n][n],c2[n][n]); ans=min(k1,k2); int x=n,y=n; for (int i=2*n-2;i>=1;i--){ if (k1<=k2) p[i]=d1[x][y]; else p[i]=d2[x][y]; if (p[i]=='D') x--; else y--; } } int main(){ scanf("%d",&n); int g[50],e[30]; g[0]=e[0]=1; for (int i=1;i<=26;i++) g[i]=g[i-1]*2; for (int i=1;i<=11;i++) e[i]=e[i-1]*5; bool q=false; int bx,by; for (int i=1;i<=n;i++) for (int j=1;j<=n;j++){ scanf("%d",&a[i][j]); if (a[i][j]==0) q=true,bx=i,by=j; for (int s=26;s>=0;s--) if (a[i][j]%g[s]==0){ h[i][j]=s; a[i][j]/=g[s]; break; } for (int s=11;s>=0;s--) if (a[i][j]%e[s]==0){ t[i][j]=s; a[i][j]/=e[s]; break; } } check1(); if (q&&ans>1){ printf("1\n"); for (int i=1;i<bx;i++) printf("D"); for (int i=1;i<n;i++) printf("R"); for (int i=1;i<=n-bx;i++) printf("D"); return 0; } printf("%d\n",ans); for (int i=1;i<=2*n-2;i++) printf("%c",p[i]); printf("\n"); }