RMQ问题是一类区间最值问题,这里给出一个特殊的RMQ问题,初始给定一个n长的排列P,注:n长排列是指有1~n这n个整数构成的一个序列每个整数恰好出现一次。并对这个排列P进行M次查询操作,每次查询形如Query(L,R),每次查询返回排列P中位置在区间[L,R]上所有数中最大的那个数,其中位置的下标从1开始。例如排列P = {3,1,4,2,5},
那么Query(1,2) = max{3,1}=3,Query(2,4)=max{1,4,2}=4。由于RMQ问题对大家来说实在是太简单了,所以这题要求大家求解一个RMQ的逆问题,即给你排列的长度n,以及M次查询的问题及其结果三元组(Li,Ri,Qi),即Query(Li,Ri)=Qi,询问符合这M次查询的n长排列是否存在。若存在输出“Possible”;否则输出“Impossible”。
Input
多组测试数据,第一行一个整数T,表示测试数据数量,1<=T<=5
之后有T组结构相同的数据:
每组数据的第一行有两个整数n与M,其中1<=n<=10^9(即1,000,000,000),1<=M<=50
之后会有M行,每行表示一个三元组Li,Ri,Qi,其中1<=Li<=Ri<=n,1<=Qi<=n
Output
每组数据输出一行,即“Possible”或“Impossible”不含引号
对于一个询问(L,R,Q),能得到的信息是(Q,n]中的数只能在[1,L)或(R,n],Q只能在[L,R]
因此离散化之后可以转化为最大流,左边的点代表每个数值/数值区间,右边的点代表每个区间,之间连边inf代表此数值可以在此区间内,源点到左边的点连边限制每个数值/数值区间中数值的个数,右边的点连边到汇点限制每个区间内数值的个数,当且仅当最大流为n时有解
#include<cstdio> #include<algorithm> const int N=100000,inf=0x3f3f3f3f; int es[N],enx[N],ev[N],e0[N],ep; int h[N],q[N],S,T; inline void adde(int a,int b,int c){ es[ep]=b;enx[ep]=e0[a];ev[ep]=c;e0[a]=ep++; es[ep]=a;enx[ep]=e0[b];ev[ep]=0;e0[b]=ep++; } bool bfs(){ int ql=0,qr=0; for(int i=0;i<=T;i++)h[i]=0; h[S]=1;q[qr++]=S; while(ql!=qr){ int w=q[ql++]; for(int i=e0[w];i;i=enx[i]){ int u=es[i]; if(!h[u]&&ev[i]){ h[u]=h[w]+1; q[qr++]=u; } } } return h[T]; } int dfs(int w,int f){ if(w==T)return f; int c,u,used=0; for(int i=e0[w];i;i=enx[i]){ u=es[i]; if(h[u]!=h[w]+1||!ev[i])continue; c=f-used; if(c>ev[i])c=ev[i]; c=dfs(u,c); used+=c; ev[i]-=c; ev[i^1]+=c; if(used==f)return f; } if(!used)h[w]=0; return used; } int qs[53][3],xs[107],ps[107],xp,pp; bool d[107][107]; int main(){ int _T,n,q; for(scanf("%d",&_T);_T;_T--){ scanf("%d%d",&n,&q); for(int i=0;i<q;i++)scanf("%d%d%d",qs[i],qs[i]+1,qs[i]+2); xp=pp=0; xs[xp++]=1; xs[xp++]=n+1; ps[pp++]=1; ps[pp++]=n+1; for(int i=0;i<q;i++){ xs[xp++]=qs[i][2]; xs[xp++]=qs[i][2]+1; ps[pp++]=qs[i][0]; ps[pp++]=qs[i][1]+1; } std::sort(xs,xs+xp); xp=std::unique(xs,xs+xp)-xs; std::sort(ps,ps+pp); pp=std::unique(ps,ps+pp)-ps; for(int i=0;i<xp;i++)for(int j=0;j<pp;j++)d[i][j]=1; for(int i=0;i<q;i++){ for(int j=0;j<xp-1;j++){ if(xs[j]>qs[i][2]){ for(int k=0;k<pp-1;k++)if(qs[i][0]<=ps[k]&&ps[k]<=qs[i][1]){ d[j][k]=0; } }else if(xs[j]==qs[i][2]){ for(int k=0;k<pp-1;k++)if(qs[i][0]>ps[k]||ps[k]>qs[i][1]){ d[j][k]=0; } } } } S=xp+pp+1;T=S+1; for(int i=1;i<=T;i++)e0[i]=0; ep=2; for(int i=0;i<xp-1;i++)adde(S,i+1,xs[i+1]-xs[i]); for(int i=0;i<pp-1;i++)adde(xp+i+1,T,ps[i+1]-ps[i]); for(int i=0;i<xp-1;i++)for(int j=0;j<pp-1;j++)if(d[i][j])adde(i+1,xp+j+1,n); int ans=0; while(bfs())ans+=dfs(S,inf); puts(ans==n?"Possible":"Impossible"); } return 0; }