一个小技巧总结
当题目是区间求和或者其他区间询问时,如果询问是离线的,而且询问涉及 l-r内有多少个不同的xxx。这个xxx可以是不同的数 不同的gcd 不同的异或和 等等
这时候我们可以把询问按右端点排序,然后把a[i]的出现永远存在靠右的一边 当i==q.r的时候 求答案
有三道例题
hdu3333
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 Problem : 3333 ( Turing Tree ) Judge Status : Accepted 2 RunId : 18401449 Language : C++ Author : GeniusYang 3 Code Render Status : Rendered By HDOJ C++ Code Render Version 0.01 Beta 4 5 #include <iostream> 6 7 #include <cstdio> 8 9 #include <string.h> 10 11 #include <vector> 12 13 #include <map> 14 15 #include <algorithm> 16 17 using namespace std; 18 19 const int maxn=30000; 20 21 typedef long long LL; 22 23 int t; 24 25 int len; 26 27 int n,q; 28 29 LL a[maxn+10]; 30 31 LL c[maxn+10]; 32 33 LL res[maxn*10+10]; 34 35 map<int,int> m; 36 37 struct qy{ 38 int l,r; 39 int id; 40 }Q[maxn*10+10]; 41 42 int cmp(qy a,qy b){ 43 return a.r<b.r; 44 } 45 46 int lowbit(int x){ 47 return x&(-x); 48 } 49 50 void modify(int x,int add){ 51 while(x<=n){ 52 c[x]+=add; 53 x+=lowbit(x); 54 } 55 } 56 57 LL get_sum(int x){ 58 LL ret=0; 59 while(x!=0){ 60 ret+=c[x]; 61 x-=lowbit(x); 62 } 63 return ret; 64 } 65 66 void init(){ 67 m.clear(); 68 memset(c,0,sizeof(c)); 69 memset(Q,0,sizeof(Q)); 70 memset(res,0,sizeof(res)); 71 } 72 73 int main() 74 { 75 scanf("%d",&t); 76 while(t--){ 77 init(); 78 scanf("%d",&n); 79 for(int i=1;i<=n;i++){ 80 scanf("%I64d",&a[i]); 81 } 82 scanf("%d",&q); 83 for(int i=1;i<=q;i++){ 84 scanf("%d%d",&Q[i].l,&Q[i].r); 85 Q[i].id=i; 86 } 87 len=1; 88 sort(Q+1,Q+q+1,cmp); 89 for(int i=1;i<=n;i++){ 90 int temp=m[a[i]]; 91 if(temp){ 92 modify(temp,-a[i]); 93 modify(i,a[i]); 94 m[a[i]]=i; 95 } else { 96 m[a[i]]=i; 97 modify(i,a[i]); 98 } 99 while(Q[len].r==i&&len<=q){ 100 res[Q[len].id]=get_sum(Q[len].r)-get_sum(Q[len].l-1); 101 len++; 102 } 103 } 104 for(int i=1;i<=q;i++){ 105 printf("%I64d\n",res[i]); 106 } 107 } 108 return 0; 109 }
hdu5869
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 Problem : 5869 ( Different GCD Subarray Query ) Judge Status : Accepted 2 RunId : 18402625 Language : G++ Author : GeniusYang 3 Code Render Status : Rendered By HDOJ G++ Code Render Version 0.01 Beta 4 5 #include <iostream> 6 7 #include <vector> 8 9 #include <algorithm> 10 11 #include <map> 12 13 #include <string.h> 14 15 using namespace std; 16 17 const int maxn=100000; 18 19 typedef pair<int,int> P; 20 21 int len; 22 23 int n,q; 24 25 vector<P> G[maxn+10]; 26 27 map<int,int> m; 28 29 int a[maxn+10]; 30 31 int c[maxn+10]; 32 33 int res[maxn*10+10]; 34 35 int gcd(int a,int b){ 36 return b==0?a:gcd(b,a%b); 37 } 38 39 struct qy{ 40 int l,r; 41 int id; 42 }Q[maxn*10+10]; 43 44 int cmp(qy a,qy b){ 45 return a.r<b.r; 46 } 47 48 int lowbit(int x){ 49 return x&(-x); 50 } 51 52 void add(int x,int y){ 53 while(x<=n){ 54 c[x]+=y; 55 x+=lowbit(x); 56 } 57 } 58 59 int sum(int x){ 60 int res=0; 61 while(x!=0){ 62 res+=c[x]; 63 x-=lowbit(x); 64 } 65 return res; 66 } 67 68 void init(){ 69 len=1; 70 m.clear(); 71 G[0].clear(); 72 memset(c,0,sizeof(c)); 73 memset(Q,0,sizeof(Q)); 74 memset(res,0,sizeof(res)); 75 } 76 77 int main() 78 { 79 while(scanf("%d%d",&n,&q)!=EOF){ 80 init(); 81 for(int i=1;i<=n;i++){ 82 G[i].clear(); 83 scanf("%d",&a[i]); 84 } 85 for(int i=1;i<=n;i++){ 86 int x=a[i],y=i; 87 for(size_t j=0;j<G[i-1].size();j++){ 88 int temp=gcd(x,G[i-1][j].first); 89 if(temp!=x){ 90 G[i].push_back(make_pair(x,y)); 91 x=temp,y=G[i-1][j].second; 92 } 93 } 94 G[i].push_back(make_pair(x,y)); 95 } 96 for(int i=1;i<=q;i++){ 97 Q[i].id=i; 98 scanf("%d%d",&Q[i].l,&Q[i].r); 99 } 100 sort(Q+1,Q+1+q,cmp); 101 for(int i=1;i<=n;i++){ 102 for(size_t j=0;j<G[i].size();j++){ 103 int t1=m[G[i][j].first]; 104 int t2=G[i][j].second; 105 if(t1){ 106 add(t1,-1); 107 } 108 add(t2,1); 109 m[G[i][j].first]=t2; 110 } 111 while(Q[len].r==i&&len<=q){ 112 res[Q[len].id]=sum(Q[len].r)-sum(Q[len].l-1); 113 len++; 114 } 115 } 116 for(int i=1;i<=q;i++){ 117 printf("%d\n",res[i]); 118 } 119 } 120 return 0; 121 }
codeforces 703D
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 3 #define inf 0x3f3f3f3f 4 5 const int maxn=1000000; 6 7 using namespace std; 8 9 typedef long long ll; 10 11 int n; 12 13 int m; 14 15 int a[maxn+10]; 16 17 int c[maxn+10]; 18 19 ll sum[maxn+10]; 20 21 ll ans[maxn+10]; 22 23 map<int,int> flag; 24 25 struct node{ 26 int l,r; 27 int id; 28 bool operator<(const node &t)const{ 29 return r<t.r; 30 } 31 }q[maxn+10]; 32 33 int lowbit(int x){ 34 return x&(-x); 35 } 36 37 void add(int x,int y){ 38 while(x<=n){ 39 c[x]^=y; 40 x+=lowbit(x); 41 } 42 } 43 44 ll get_sum(int x){ 45 ll res=0; 46 while(x){ 47 res^=c[x]; 48 x-=lowbit(x); 49 } 50 return res; 51 } 52 53 int cmp(node a,node b){ 54 return a.id<b.id; 55 } 56 57 int main() 58 { 59 scanf("%d",&n); 60 for(int i=1;i<=n;i++){ 61 scanf("%d",&a[i]); 62 sum[i]=sum[i-1]^a[i]; 63 } 64 scanf("%d",&m); 65 for(int i=1;i<=m;i++){ 66 scanf("%d%d",&q[i].l,&q[i].r); 67 q[i].id=i; 68 } 69 sort(q+1,q+1+m); 70 int len=1; 71 for(int i=1;i<=n;i++){ 72 int temp=flag[a[i]]; 73 if(temp){ 74 add(temp,a[i]); 75 flag[a[i]]=i; 76 add(i,a[i]); 77 } else { 78 flag[a[i]]=i; 79 add(i,a[i]); 80 } 81 while(q[len].r==i){ 82 ans[q[len].id]=get_sum(q[len].r)^get_sum(q[len].l-1)^sum[q[len].r]^sum[q[len].l-1]; 83 len++; 84 } 85 } 86 sort(q+1,q+1+m,cmp); 87 for(int i=1;i<=m;i++){ 88 printf("%I64d\n",ans[i]); 89 } 90 return 0; 91 }