8.21 usaco
summary:6
bzoj1692://后缀数组就行了O(nlogn)c[30]会RE。。。注意!!!
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=60005; const int inf=0x7f7f7f7f; char ss[5];int s[nmax],sa[nmax],t[nmax],t2[nmax],rank[nmax],c[nmax],n; void build_sa(){ int *x=t,*y=t2,m=29; for(int i=0;i<m;i++) c[i]=0; for(int i=0;i<n;i++) c[x[i]=s[i]]++; for(int i=1;i<m;i++) c[i]+=c[i-1]; for(int i=n-1;i>=0;i--) sa[--c[x[i]]]=i; for(int k=1;k<=n;k<<=1){ int p=0; for(int i=n-k;i<n;i++) y[p++]=i; for(int i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k; for(int i=0;i<m;i++) c[i]=0; for(int i=0;i<n;i++) c[x[i]]++; for(int i=1;i<m;i++) c[i]+=c[i-1]; for(int i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i]; swap(x,y);p=1;x[sa[0]]=0; for(int i=1;i<n;i++) x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++; if(p>=n) break; m=p; } } int main(){ n=read(); rep(i,0,n-1) scanf("%s",ss),s[i]=ss[0]-'A'+1; s[n]=0; rep(i,1,n) s[n+i]=s[n-i]; int tn=n;n*=2;++n; build_sa(); rep(i,0,n-1) rank[sa[i]]=i; int l=0,r=tn-1;; rep(i,1,tn){ if(rank[l]<rank[tn-r+tn]) putchar(s[l++]+'A'-1); else putchar(s[r--]+'A'-1); if(i%80==0) putchar('\n'); } return 0; }
bzoj1697:置换群(感觉好神啊。。。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) int read(){ int x=0,f=1;char c=getchar(); while(!isdigit(c)) { if(c=='-') f=-1;c=getchar(); } while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x*f; } const int nmax=1e4+5; const int maxn=1e5+5; const int inf=0x7f7f7f7f; int a[nmax],to[maxn],b[nmax],mn,n; bool vis[nmax]; void mins(int &a,int b){ if(a>b) a=b; } int solve(int x){ int tmn=a[x],cnt=1,sum=a[x];vis[x]=1; for(int tmp=to[b[x]];tmp!=x;tmp=to[b[tmp]]) cnt++,mins(tmn,a[tmp]),sum+=a[tmp],vis[tmp]=1; return min(sum+(cnt-2)*tmn,sum+tmn+(cnt+1)*mn); } int main(){ n=read(),mn=inf; rep(i,1,n) a[i]=b[i]=read(),mins(mn,a[i]),to[a[i]]=i; sort(b+1,b+n+1); int ans=0; rep(i,1,n) if(!vis[i]) ans+=solve(i); printf("%d\n",ans); return 0; }
bzoj1703:bitset优化传递闭包。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<bitset> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) #define qwq(x) for(edge *o=head[x];o;o=o->next) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=1005; const int maxn=10005; const int inf=0x7f7f7f7f; bitset<nmax>a[nmax]; struct edge{ int to;edge *next; }; edge es[maxn],*pt=es,*head[nmax]; bool vis[nmax]; void add(int u,int v){ pt->to=v;pt->next=head[u];head[u]=pt++; } void dfs(int x){ vis[x]=1; qwq(x) { if(!vis[o->to]) dfs(o->to); a[x]|=a[o->to]; } } int main(){ int n=read(),m=read(),u,v; rep(i,1,m) u=read(),v=read(),add(u,v); rep(i,1,n) a[i][i]=1; rep(i,1,n) if(!vis[i]) dfs(i); int ans=0; rep(i,1,n) printf("%d ",a[i].count());printf("\n"); rep(i,1,n) ans+=a[i].count(); printf("%d\n",n*(n-1)/2-ans+n); return 0; }
bzoj1704:写了O(n^3)想要卡过去结果tle了。。。异或异或异或!!!可以利用异或的性质O(n^2)
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) const int nmax=5005; const int inf=0x7f7f7f7f; char s[5];int a[nmax],b[nmax]; int main(){ int n;scanf("%d",&n); rep(i,1,n) { scanf("%s",s); a[i]=s[0]=='F'?0:1; } dwn(i,n,2) a[i]=a[i]==a[i-1]?0:1; int ans,res=inf,cnt;bool flag; rep(i,1,n) { cnt=0;flag=true; rep(j,1,n) b[j]=a[j]; rep(j,1,n) if(b[j]) { if(j+i-1<=n) cnt++,b[j+i]^=1; else { flag=false;break; } } if(flag&&cnt<res) ans=i,res=cnt; } printf("%d %d\n",ans,res); return 0; }
ch11:没有考虑0.499999的情况WA了一个点还好没有卡精度啊QAQ看题不仔细!懒得改了。。。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define clr(x,c) memset(x,c,sizeof(x)) int read(){ int x=0,f=1;char c=getchar(); while(!isdigit(c)){ if(c=='-') f=-1;c=getchar(); } while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x*f; } int main(){ double sum=0; int t=read(); while(t--){ int n=read(),u; double sum=0; rep(i,1,n) u=read(),sum+=u*1.0; if(sum-0.5*n<=100.0&&sum+0.4*n>=100.0) printf("Yes\n"); else printf("No\n"); } return 0; }
ch12:树状数组+n数码判有无解。没有看好数据范围没开longlong。。。都是一些以为自己不会犯的错误啊。。。懒得改了。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define clr(x,c) memset(x,c,sizeof(x)) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=250005; int sum[nmax],n; int query(int x){ int ans=0; for(int i=x;i;i-=i&-i) ans+=sum[i]; return ans; } void add(int x){ for(int i=x;i<=n*n;i+=i&-i) sum[i]+=1; } int main(){ while(scanf("%d",&n)!=EOF){ clr(sum,0); int u,ans=0,res=0; rep(i,1,n) rep(j,1,n){ u=read();if(!u) continue; ans+=query(u);add(u); } clr(sum,0); rep(i,1,n) rep(j,1,n) { u=read();if(!u) continue; res+=query(u);add(u); } if((ans%2)!=(res%2)) printf("NIE\n"); else printf("TAK\n"); } return 0; }