題意
給出一個長度為n的序列,有m次詢問,每次詢問[l1,r1],[l2,r2]的區間,問排序後相同位置的不同數字個數是否小於等於1。如[1,3,2,2],[1,3,2,3]排序後為[1,2,2,3]和[1,2,3,3],不同的有2個,不符合。n,m≤1,000,000,數的大小≤50,000。
思考
有排序,權值還小,自然想到可持久化線段樹。
不同數小於等於1,自然先想完全相同的條件。
先以權值為下表,按加入陣列的順序加入可持久化線段樹,這樣得到了1~n不同大小的數的字首和。
若是完全相同,先做一次r-(l-1),由於排序後的數,相同的沒有位置關係,雜湊即可。
有一個不同?則必然存在最左邊和最右邊的端點,使得該位置上出現的數的個數不同。不同的數超過2個,及不符合(實際上是1,但會算兩邊)。否則再查詢這個開區間中,是否還有其餘數。若有,顯然不滿足。否則滿足。
線段樹上二分即可。O(nlogn+mlogn)。
記得不要用hash這個變數名就能過了。
程式碼
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long int ll; 4 const ll h1=13131; 5 const ll h2=23333; 6 const ll h3=15787; 7 const ll mod1=1000000007; 8 const ll mod2=998244353; 9 const ll mod3=19260817; 10 const ll maxn=1E5+5; 11 ll q1[maxn],q2[maxn],q3[maxn],maxx=100000; 12 int read() 13 { 14 char ch=getchar(); 15 while(ch<'0'||'9'<ch)ch=getchar(); 16 int sum=ch-'0'; 17 ch=getchar(); 18 while('0'<=ch&&ch<='9') 19 { 20 sum=sum*10+ch-'0'; 21 ch=getchar(); 22 } 23 return sum; 24 } 25 struct Hash 26 { 27 ll a1,a2,a3; 28 int sum; 29 Hash(ll x=0,ll y=0,ll z=0,ll s=0){a1=(x+mod1)%mod1,a2=(y+mod2)%mod2,a3=(z+mod3)%mod3,sum=s;} 30 void operator=(Hash x){a1=x.a1,a2=x.a2,a3=x.a3,sum=x.sum;} 31 Hash operator+(Hash x){return Hash(a1+x.a1,a2+x.a2,a3+x.a3,sum+x.sum);} 32 Hash operator-(Hash x){return Hash(a1-x.a1,a2-x.a2,a3-x.a3,sum-x.sum);} 33 bool operator==(Hash x){return a1==x.a1&&a2==x.a2&&a3==x.a3;} 34 }t[maxn*20],g[maxn]; 35 int ls[maxn*20],rs[maxn*20],T,n,m,cur,a[maxn],root[maxn]; 36 void init() 37 { 38 q1[0]=q2[0]=q3[0]=1; 39 for(int i=1;i<=100000;++i) 40 { 41 q1[i]=q1[i-1]*h1%mod1; 42 q2[i]=q2[i-1]*h2%mod2; 43 q3[i]=q3[i-1]*h3%mod3; 44 g[i]=Hash(q1[i],q2[i],q3[i],1); 45 } 46 } 47 void insert(int l,int r,int pos,int&num,int pre) 48 { 49 num=++cur; 50 t[num]=t[pre]; 51 ls[num]=ls[pre]; 52 rs[num]=rs[pre]; 53 t[num]=t[num]+g[pos]; 54 if(l==r)return; 55 int mid=(l+r)>>1; 56 if(pos<=mid)insert(l,mid,pos,ls[num],ls[pre]); 57 else insert(mid+1,r,pos,rs[num],rs[pre]); 58 } 59 int GGAx,GGAy,GGAz,GGBx,GGBy,GGBz; 60 void findL(int l,int r,int l1,int r1,int l2,int r2) 61 { 62 if(l==r) 63 { 64 GGAx=l; 65 GGAy=t[r1].sum-t[l1].sum; 66 GGAz=t[r2].sum-t[l2].sum; 67 return; 68 } 69 int mid=(l+r)>>1; 70 Hash L1=t[ls[r1]]-t[ls[l1]],R1=t[rs[r1]]-t[rs[l1]]; 71 Hash L2=t[ls[r2]]-t[ls[l2]],R2=t[rs[r2]]-t[rs[l2]]; 72 if(!(L1==L2)) 73 { 74 l1=ls[l1],r1=ls[r1]; 75 l2=ls[l2];r2=ls[r2]; 76 findL(l,mid,l1,r1,l2,r2); 77 } 78 else 79 { 80 l1=rs[l1],r1=rs[r1]; 81 l2=rs[l2],r2=rs[r2]; 82 findL(mid+1,r,l1,r1,l2,r2); 83 } 84 } 85 void findR(int l,int r,int l1,int r1,int l2,int r2) 86 { 87 if(l==r) 88 { 89 GGBx=l; 90 GGBy=t[r1].sum-t[l1].sum; 91 GGBz=t[r2].sum-t[l2].sum; 92 return; 93 } 94 int mid=(l+r)>>1; 95 Hash L1=t[ls[r1]]-t[ls[l1]],R1=t[rs[r1]]-t[rs[l1]]; 96 Hash L2=t[ls[r2]]-t[ls[l2]],R2=t[rs[r2]]-t[rs[l2]]; 97 if(!(R1==R2)) 98 { 99 l1=rs[l1],r1=rs[r1]; 100 l2=rs[l2],r2=rs[r2]; 101 findR(mid+1,r,l1,r1,l2,r2); 102 } 103 else 104 { 105 l1=ls[l1],r1=ls[r1]; 106 l2=ls[l2];r2=ls[r2]; 107 findR(l,mid,l1,r1,l2,r2); 108 } 109 } 110 int askSeq(int L,int R,int l,int r,int num) 111 { 112 if(L>R)return 0; 113 if(L<=l&&r<=R)return t[num].sum; 114 else if(r<L||R<l)return 0; 115 int mid=(l+r)>>1; 116 return askSeq(L,R,l,mid,ls[num])+askSeq(L,R,mid+1,r,rs[num]); 117 } 118 void YES(){putchar('Y');putchar('E');putchar('S');putchar('\n');} 119 void NO(){putchar('N');putchar('O');putchar('\n');} 120 void solve() 121 { 122 n=read();m=read(); 123 for(int i=1;i<=n;++i) 124 { 125 a[i]=read(); 126 insert(1,maxx,a[i],root[i],root[i-1]); 127 } 128 while(m--) 129 { 130 int l1,r1,l2,r2; 131 l1=read();r1=read();l2=read();r2=read(); 132 if(l1>r1)swap(l1,r1); 133 if(l2>r2)swap(l2,r2); 134 if(t[root[r1]]-t[root[l1-1]]==t[root[r2]]-t[root[l2-1]])YES(); 135 else 136 { 137 findL(1,maxx,root[l1-1],root[r1],root[l2-1],root[r2]); 138 findR(1,maxx,root[l1-1],root[r1],root[l2-1],root[r2]); 139 int x=GGAx; 140 int y=GGBx; 141 int d1=askSeq(x+1,y-1,1,maxx,root[r1])-askSeq(x+1,y-1,1,maxx,root[l1-1]); 142 int d2=askSeq(x+1,y-1,1,maxx,root[r2])-askSeq(x+1,y-1,1,maxx,root[l2-1]); 143 if(abs(GGAy-GGAz)+abs(GGBy-GGBz)>2||d1!=0||d2!=0)NO(); 144 else YES(); 145 } 146 } 147 } 148 void clear() 149 { 150 for(int i=0;i<=cur;++i)t[i].a1=t[i].a2=t[i].a3=ls[i]=rs[i]=0; 151 for(int i=0;i<=n;++i)root[i]=0; 152 cur=0; 153 } 154 int main() 155 { 156 // freopen("sequence.in","r",stdin); 157 // freopen("sequence.out","w",stdout); 158 ios::sync_with_stdio(false); 159 init(); 160 T=read(); 161 while(T--) 162 { 163 solve(); 164 if(T!=0)clear(); 165 } 166 return 0; 167 }