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");
}
}