前缀+树状数组

Different Integers

 

具体见代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn=1e5+10;
 5 const int mod=1e9+7;
 6 #define rep(i,first,second) for(int i=first;i<=second;i++)
 7 #define dep(i,first,second) for(int i=first;i>=second;i--)
 8 
 9 struct node{//右端点大的优先
10     int l,r,id;
11     bool operator < (const node &a) const{
12         if( r==a.r ) return l<a.l;
13         return r>a.r;
14     }
15 }s[maxn];
16 
17 int n,m,a[maxn];
18 int first[maxn];//记录从前往后不同数的个数
19 int vis[maxn];
20 int sum[maxn];
21 int lowbit(int x){ return x&-x;}
22 void update(int pos,int val){
23     while( pos<=n ){
24         sum[pos]+=val;
25         pos+=lowbit(pos);
26     }
27 }
28 int query(int pos){
29     int ans=0;
30     while( pos>0 ){
31         ans+=sum[pos];
32         pos-=lowbit(pos);
33     }
34     return ans;
35 }
36 int pre[maxn],ans[maxn];
37 int main()
38 {
39     while( ~scanf("%d%d",&n,&m)){
40         memset(first,0,sizeof(first));
41         int res=0;//记录从后往前不同数的个数
42         rep(i,1,n){
43             scanf("%d",&a[i]);
44             if( !first[a[i]] ){
45                 first[a[i]]=i;
46                 res++;
47             }
48             pre[i]=res;//记下i位置前面不同数的个数
49         }
50         rep(i,1,m){
51             scanf("%d%d",&s[i].l,&s[i].r);
52             s[i].id=i;
53         }
54         sort(s+1,s+1+m);
55         memset(sum,0,sizeof(sum));
56         memset(vis,0,sizeof(vis));
57         res=0;//记录从后往前不同数的个数
58         int r=n+1;
59         rep(i,1,m){
60             while( r>s[i].r ){
61                 r--;
62                 if( !vis[a[r]]){
63                     res++;
64                     vis[a[r]]=1;
65                     update(first[a[r]],1);
66                 }
67             }
68             ans[s[i].id]=pre[s[i].l]+res-query(s[i].l);//s[i].l以前不同的个数+res-前后重复出现的数量
69         }
70         rep(i,1,m) printf("%d
",ans[i]);
71     }
72     return 0;
73 }

Mishka and Interesting sum

 

 分析:每一次询问的答案,等于 这个区间所有不同元素异或和 异或上 区间异或和。(因为出现偶数次的对区间异或和贡献为0,此时剩下的是出现奇数次的数,在取个补集即为答案);x^x=0,x^0=x;

 1 //每一次询问的答案,等于 这个区间所有不同元素异或和 异或上 区间异或和。(因为出现偶数次的对区间异或和贡献为0,此时剩下的是出现奇数次的数,在取个补集即为答案)
 2 //x^x=0,x^0=x;
 3 #include <bits/stdc++.h>
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxn=1e6+10;
 7 const int mod=1e9+7;
 8 #define rep(i,first,second) for(int i=first;i<=second;i++)
 9 #define dep(i,first,second) for(int i=first;i>=second;i--)
10 
11 struct node{
12     int id,l,r;
13     bool operator < (const node &a) const{
14         return r<a.r;
15     }
16 }e[maxn];
17 
18 int tree[maxn],sum[maxn],a[maxn];
19 map<int,int>vis;
20 int n,ans[maxn],m;
21 
22 int lowbit(int x){ return x&(-x);}
23 void update(int pos,int val){
24     while( pos<=n ){
25         tree[pos]^=val;
26         pos+=lowbit(pos);
27     }
28 }
29 int query(int x){
30     int res=0;
31     while( x ){
32         res^=tree[x];
33         x-=lowbit(x);
34     }
35     return res;
36 }
37 
38 int main()
39 {
40     scanf("%d",&n);
41     rep(i,1,n){
42         scanf("%d",&a[i]);
43         sum[i]=sum[i-1]^a[i];
44     }
45     scanf("%d",&m);
46     rep(i,1,m){
47         scanf("%d%d",&e[i].l,&e[i].r);
48         e[i].id=i;
49     }
50     sort(e+1,e+1+m);
51 
52     int p=1;
53     rep(i,1,m){
54         int l=e[i].l,r=e[i].r;
55         while( p<=r ){
56             if( !vis[a[p]] ){//第一次出现
57                 vis[a[p]]=p;//记录位置
58                 update(p,a[p]);
59             }
60             else{
61                 update(vis[a[p]],a[p]);//在现区间出现过,则原位置清零
62                 update(p,a[p]);
63                 vis[a[p]]=p;
64             }
65             p++;
66         }
67         ans[e[i].id]=sum[r]^sum[l-1]^query(r)^query(l-1);//在现区间没有出现过的数通过query(r)^query(l-1)清零
68     }
69     rep(i,1,m) printf("%d
",ans[i]);
70     return 0;
71 }

 

原文地址:https://www.cnblogs.com/wsy107316/p/12904025.html