一个小技巧总结

当题目是区间求和或者其他区间询问时,如果询问是离线的,而且询问涉及 l-r内有多少个不同的xxx。这个xxx可以是不同的数 不同的gcd 不同的异或和 等等

这时候我们可以把询问按右端点排序,然后把a[i]的出现永远存在靠右的一边 当i==q.r的时候 求答案

有三道例题

hdu3333

  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
",res[i]);
106        }
107     }
108     return 0;
109 }
View Code

hdu5869

  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
",res[i]);
118         }
119     }
120     return 0;
121 }
View Code

codeforces 703D

 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
",ans[i]);
89     }
90     return 0;
91 }
View Code
原文地址:https://www.cnblogs.com/GeniusYang/p/5996577.html