貌似是先把各个子串处理成各个Hash值,然后离散化,然后这道题就变成询问区间[x,y]中有没有数字k。
主席树直接上。。。
#include#include #include #include #include #include #include #define rep(i, l, r) for(int i=l; i<=r; i++)#define clr(x, c) memset(x, c, sizeof(x))#define lowbit(x) (x&-x)#define maxn 600009#define maxm 5000009#define hash 2333#define inf 0x7fffffff#define s(x) Sum[x]#define t(x) Tree[x]#define l(x) Left[x]#define r(x) Right[x]#define k(x) Key[x]#define ull unsigned long longusing namespace std;inline int read(){ int x=0, f=1; char ch=getchar(); while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while (isdigit(ch)) x=x*10+ch-'0', ch=getchar(); return x*f;}struct node{ull v; int t;} q[maxn];bool cmp(node a, node b){return a.v >1; if (k<=mid) r(t)=r(u), Add(k, l, mid, l(u), l(t)); else l(t)=l(u), Add(k, mid+1, r, r(u), r(t));}inline bool Query(int l, int r, int k){ int L=1, R=ln, x=t(l-1), y=t(r); while (L >1; if (k<=mid) R=mid, x=l(x), y=l(y); else L=mid+1, x=r(x), y=r(y); } if (s(y)-s(x)) return true; else return false;}int main(){ n=read(), m=read(), k=read(); t(0)=++z, l(z)=r(z)=z; rep(i, 1, n) a[i]=read(); rep(i, 1, n-k+1) q[i].v=Hash(i), q[i].t=i; n=n-k+1; rep(i, 1, m) { qx[i]=read(), qy[i]=read()-k+1; rep(j, 1, k) a[j]=read(); q[i+n].v=Hash(1), q[i+n].t=i+n; } sort(q+1, q+m+n+1, cmp); k(q[1].t)=++ln; rep(i, 2, n+m) k(q[i].t) = q[i].v!=q[i-1].v ? ++ln : ln; rep(i, 1, n) Add(k(i), 1, ln, t(i-1), t(i)); rep(i, 1, m) if (Query(qx[i], qy[i], k(i+n))) printf("No\n"); else printf("Yes\n"); return 0;}