好气啊,本来以为比赛时间还有很多,结果回家养病两天回到学校怎么比赛就结束了(雾),大约是小高考弄错了时间?
挑3道有意思的写写题解吧。
题目大意:给一个序列,每次询问两个等长区间,问区间内的数是否排序后至多只有一个对应位不同。
题解:主席树维护一下hash,求出最大的k,使得两个区间中的前k大在排序后相同,然后判一下后缀即可。
#include<cstdio> #include<algorithm> #define MN 110000 #define ull unsigned long long using namespace std; int read_p,read_ca; inline int read(){ read_p=0;read_ca=getchar(); while(read_ca<'0'||read_ca>'9') read_ca=getchar(); while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar(); return read_p; } const ull base=2636363; int T,n,m,ro[MN],num=0,a,b,c,d; ull H[MN]; struct na{int l,r,s;ull h;na(){s=h=0;}}t[MN*20]; inline void add(int &p,int x,int l,int r,int k){ p=++num;t[p]=t[x]; t[p].h+=H[k];t[p].s++; if (l==r) return; int mid=l+r>>1; if (k<=mid) add(t[p].l,t[x].l,l,mid,k);else add(t[p].r,t[x].r,mid+1,r,k); } inline int aski(int a,int b,int c,int d,int l,int r){ if (t[b].h-t[a].h==t[d].h-t[c].h&&t[b].s-t[a].s==t[d].s-t[c].s) return t[b].s-t[a].s; if (l==r) return min(t[b].s-t[a].s,t[d].s-t[c].s); int mid=l+r>>1; int mmh=aski(t[a].l,t[b].l,t[c].l,t[d].l,l,mid); if (mmh==t[t[b].l].s-t[t[a].l].s&&mmh==t[t[d].l].s-t[t[c].l].s) mmh+=aski(t[a].r,t[b].r,t[c].r,t[d].r,mid+1,r); return mmh; } inline int aska(int a,int b,int c,int d,int l,int r){ if (t[b].h-t[a].h==t[d].h-t[c].h&&t[b].s-t[a].s==t[d].s-t[c].s) return t[b].s-t[a].s; if (l==r) return min(t[b].s-t[a].s,t[d].s-t[c].s); int mid=l+r>>1; int mmh=aska(t[a].r,t[b].r,t[c].r,t[d].r,mid+1,r); if (mmh==t[t[b].r].s-t[t[a].r].s&&mmh==t[t[d].r].s-t[t[c].r].s) mmh+=aska(t[a].l,t[b].l,t[c].l,t[d].l,l,mid); return mmh; } int main(){ int i; T=read(); H[1]=1; for (i=2;i<=1e5;i++) H[i]=H[i-1]*base; while(T--){ n=read();m=read();num=0; for (i=1;i<=n;i++) add(ro[i],ro[i-1],1,1e5,read()); while(m--){ a=read();b=read();c=read();d=read(); puts(aska(ro[a-1],ro[b],ro[c-1],ro[d],1,1e5)+aski(ro[a-1],ro[b],ro[c-1],ro[d],1,1e5)>=b-a?"YES":"NO"); } } }