zoukankan      html  css  js  c++  java
  • 前缀+树状数组

    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 }

     

  • 相关阅读:
    域渗透:ptk(pass the key)
    QQ拼音输入法6.0 DLL劫持实现提权
    进程关系
    进程控制
    进程环境
    系统数据文件和信息
    文件和目录
    标准I/O
    文件描述符标志/文件表项
    SSL安全原理
  • 原文地址:https://www.cnblogs.com/wsy107316/p/12904025.html
Copyright © 2011-2022 走看看