hdu5592 - ZYB‘s Premutation
http://acm.hdu.edu.cn/showproblem.php?pid=5592
对于一个X=a[i]-a[i-1],它可以表示为原排列第i个位置的数,在它前面有X个比它大的数,也就是说在1到i的区间内第i个数为该区间内第X+1大的数
那么可以考虑倒着求出原排列:对于最后一个数,令k=a[n]-a[n-1],最后一个数就是k+1;而对于倒数第二个数,令k‘=a[n-1]-a[n-2],则该位置的答案为从1到n中除去k,第k‘+1大的数。。。以此类推
所以可以用线段树维护以上操作
#include<bits/stdc++.h> #define MAXN 50005 using namespace std; int sum[MAXN*4],n; inline void build(int l,int r,int pos) { if(l==r) { sum[pos]=1; return; } int mid=l+r>>1; build(l,mid,pos<<1); build(mid+1,r,pos<<1|1); sum[pos]=sum[pos<<1]+sum[pos<<1|1]; } inline int query(int l,int r,int k,int pos) { sum[pos]--; if(l==r) { sum[pos]=0; return l; } int mid=l+r>>1; if(k<=sum[pos<<1]) return query(l,mid,k,pos<<1); else return query(mid+1,r,k-sum[pos<<1],pos<<1|1); } int a[MAXN],ans[MAXN]; int main() { int T; scanf("%d",&T); while(T--) { scanf("%d",&n); memset(sum,0,sizeof(sum)); build(1,n,1); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=n;i>=1;i--) { int x=a[i]-a[i-1]+1; ans[i]=query(1,n,i-x+1,1); } for(int i=1;i<=n;i++) printf("%d%c",ans[i],(i==n)?‘\n‘:‘ ‘); } }
hdu5593 - ZYB‘s Tree
http://acm.hdu.edu.cn/showproblem.php?pid=5593
树形dp
设ans[i][j]为第i个点距离为j的点的个数
ans[i][j]有两部分构成:一部分来源它的子树,一部分来源它的父亲
设它的子树的答案为f[i][j],它的父亲的答案为g[i][j]
所以 ans[i][j]=f[i][j]+g[i][j];
f[i][j]=Σf[son][j-1]
g[i][j]=ans[fa][j-1]-f[i][j-2]
#include<bits/stdc++.h> #define MAXN 500050 using namespace std; struct Edge { int v,next; }e[MAXN*2]; int head[MAXN],cnt=0; inline void add(int u,int v){cnt++;e[cnt].v=v;e[cnt].next=head[u];head[u]=cnt;} int ans[MAXN][12],f[MAXN][12],g[MAXN][12],n,k,a,b; void dfs(int x,int fa) { f[x][0]=1; for(int i=head[x];i;i=e[i].next) { int v=e[i].v; if(v==fa) continue; dfs(v,x); for(int j=1;j<=k;j++) f[x][j]+=f[v][j-1]; } } void dfs1(int x,int fa) { if(fa==0) { for(int i=0;i<=k;i++) ans[x][i]=f[x][i]; } else { g[x][0]=0;ans[x][0]=1; g[x][1]=1;ans[x][1]=f[x][1]+g[x][1]; for(int i=2;i<=k;i++) { g[x][i]=ans[fa][i-1]-f[x][i-2]; ans[x][i]=f[x][i]+g[x][i]; } } for(int i=head[x];i;i=e[i].next) { int v=e[i].v; if(v==fa) continue; dfs1(v,x); } } int main() { int T; scanf("%d",&T); while(T--) { cnt=0; memset(head,0,sizeof(head)); memset(f,0,sizeof(f)); memset(g,0,sizeof(g)); memset(ans,0,sizeof(ans)); scanf("%d%d%d%d",&n,&k,&a,&b); for(int i=2;i<=n;i++) { int fa=((long long)a*i+b)%(i-1)+1; add(fa,i);add(i,fa); } dfs(1,0);dfs1(1,0); int Ans=0; for(int i=1;i<=n;i++) { int res=0; for(int j=0;j<=k;j++) res+=ans[i][j]; Ans^=res; } printf("%d\n",Ans); } }
hdu5594 - ZYB‘s Prime
http://acm.hdu.edu.cn/showproblem.php?pid=5594
官方题解:
#include<bits/stdc++.h> #define MAXN 100050 #define inf 0x3f3f3f3f using namespace std; inline int read() { int 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; } struct Edge { int v,cap,next; }e[MAXN]; int head[MAXN],cnt=1; inline void addedge(int u,int v,int cap) { e[++cnt]=(Edge){v,cap,head[u]};head[u]=cnt; e[++cnt]=(Edge){u,0,head[v]};head[v]=cnt; } bool vis[MAXN]; int dis[MAXN],cur[MAXN],S,T,n; bool bfs() { queue<int>q; memset(vis,0,sizeof(vis)); q.push(S);dis[S]=0;vis[S]=1; while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];i;i=e[i].next) { int v=e[i].v; if(vis[v]||e[i].cap==0) continue; dis[v]=dis[u]+1; vis[v]=1; q.push(v); } } return vis[T]; } int dfs(int x,int a) { if(x==T||a==0) return a; int flow=0; for(int &i=cur[x];i;i=e[i].next) { int v=e[i].v; if(dis[v]==dis[x]+1&&e[i].cap) { int f=dfs(v,min(e[i].cap,a-flow)); if(f) { e[i].cap-=f; e[i^1].cap+=f; flow+=f; } if(flow==a) break; } } return flow; } inline int maxflow() { int ans=0,flow; while(bfs()) { for(int i=S;i<=T+5;i++) cur[i]=head[i]; while(flow=dfs(S,inf)) ans+=flow; } return ans; } inline bool isprime(int x) { for(int i=2;i<=sqrt(x);i++) if(x%i==0) return 0; return 1; } int a1[205],a2[205],s1,s2,s3; int main() { int TT=read(); while(TT--) { memset(head,0,sizeof(head)); cnt=1;s1=s2=s3=0; n=read(); for(int i=1;i<=n;i++) { int x=read(); if(x&1) { if(x==1) s3++; else a1[++s1]=x; } else a2[++s2]=x; } if(s1>s2||s1+s3<s2) { puts("NO"); continue; } if(s1==s2&&s3==2) { puts("NO"); continue; } S=0,T=2*s2+1; for(int i=1;i<=s2;i++) addedge(S,i,2),addedge(i+s2,T,2); for(int i=1;i<=s1;i++) for(int j=1;j<=s2;j++) if(isprime(a1[i]+a2[j])) addedge(i,j+s2,1); int x; if(s3>s2-s1) x=2; else x=1; for(int i=1;i<=s2-s1;i++) for(int j=1;j<=s2;j++) if(isprime(1+a2[j])) addedge(i+s1,j+s2,x); if(maxflow()==2*s2) puts("YES"); else puts("NO"); } }