zoukankan      html  css  js  c++  java
  • HDU 3333 | Codeforces 703D 树状数组、离散化

    HDU 3333:http://acm.hdu.edu.cn/showproblem.php?pid=3333

    这两个题是类似的,都是离线处理查询,对每次查询的区间的右端点进行排序。这里我们需要离散化处理一下,标记一下前面是否出现过这个值,然后不断更新last数组(该数组保存的是每个数最后一次出现的位置)。最后用树状数组维护。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int maxn = 33333;
     5 const int maxq = 111111;
     6 struct node{
     7     int l,r,index;
     8 };
     9 node query[maxq];
    10 ll sum[maxn],ans[maxq];
    11 ll a[maxn],b[maxn],last[maxn];
    12 int n;
    13 bool cmp(node a,node b){
    14     return a.r < b.r;
    15 }
    16 ll getsum(int i){
    17     ll s = 0;
    18     while(i > 0){
    19         s += sum[i];
    20         i -= i&(-i);
    21     }
    22     return s;
    23 }
    24 void add(int i,ll x){
    25     while(i <= n){
    26         sum[i] += x;
    27         i += i&(-i);
    28     }
    29 }
    30 int main(){
    31     int t;
    32     scanf("%d",&t);
    33     while(t--){
    34         scanf("%d",&n);
    35         for(int i = 1;i<=n;i++){
    36             scanf("%I64d",&a[i]);
    37             b[i] = a[i];//离散化用 
    38         }
    39         sort(b+1,b+1+n);//排序,以每个数的下标标记 
    40         int q;
    41         scanf("%d",&q);
    42         for(int i = 1;i<=q;i++){
    43             scanf("%d%d",&query[i].l,&query[i].r);
    44             query[i].index = i;
    45         }
    46         sort(query+1,query+1+q,cmp);
    47         memset(sum,0,sizeof(sum));
    48         memset(last,0,sizeof(last));
    49         int cnt = 1;//每个查询的下标 
    50         for(int i = 1;i<=n;i++){
    51             int index = lower_bound(b+1,b+1+n,a[i])-b-1;//找到该数对应的下标 
    52             if(last[index])//判断该数是否出现过,有的话减去 
    53                 add(last[index],-a[i]);
    54             add(i,a[i]);
    55             last[index] = i;
    56             while(query[cnt].r==i && cnt<=q){
    57                 ans[query[cnt].index] = getsum(query[cnt].r)-getsum(query[cnt].l-1);
    58                 cnt++;
    59             }
    60         }
    61         for(int i = 1;i<=q;i++)
    62             printf("%I64d
    ",ans[i]);
    63     }    
    64     return 0;
    65 } 
    View Code

    Codeforces 703D:http://codeforces.com/contest/703/problem/D

    这道题需要多思考的一步是,要求的区间内出现偶数次的数的异或和,等于这个区间内所有数字的异或和异或这个区间内不同数字的异或和,以1、2、1、3、3、2、3举例,结果就是(1^2^1^3^3^2^3)^(1^2^3),原理就是出现偶数次的数异或它自己等于它本身,出现奇数次的数异或它自己为0。对于区间的异或和,我们可以用数组很方便的求出,不同数字的异或和,只需要对上题进行一下改造就好了。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 
     5 const int maxn = 1111111;
     6 struct node{
     7     int l,r,index;
     8 };
     9 node query[maxn];
    10 ll sum[maxn],a[maxn],b[maxn],c[maxn],last[maxn],ans[maxn];
    11 int n;
    12 bool cmp(node a,node b){
    13     return a.r < b.r;
    14 }
    15 ll getsum(int i){
    16     ll s = 0;
    17     while(i > 0){
    18         s ^= sum[i];//注意 
    19         i -= i&(-i);
    20     }
    21     return s;
    22 }
    23 void add(int i,ll x){
    24     while(i <= n){
    25         sum[i] ^= x;//注意 
    26         i += i&(-i);
    27     }
    28 }
    29 int main(){
    30     scanf("%d",&n);
    31     for(int i = 1;i<=n;i++){
    32         scanf("%I64d",&a[i]);
    33         c[i] = a[i]^c[i-1];//求前缀异或和 
    34         b[i] = a[i];
    35     }
    36     sort(b+1,b+1+n);
    37     int q;
    38     scanf("%d",&q);
    39     for(int i = 1;i<=q;i++){
    40         scanf("%d%d",&query[i].l,&query[i].r);
    41         query[i].index = i;
    42     }
    43     sort(query+1,query+1+q,cmp);
    44     int cnt = 1;
    45     for(int i = 1;i<=n;i++){
    46         int index = lower_bound(b+1,b+1+n,a[i])-b-1;
    47         if(last[index])
    48             add(last[index],a[i]);
    49         last[index] = i;
    50         add(i,a[i]);
    51         while(query[cnt].r==i && cnt<=q){
    52             ans[query[cnt].index] = (c[query[cnt].r]^c[query[cnt].l-1])^(getsum(query[cnt].r)^getsum(query[cnt].l-1));//注意 
    53             cnt++;
    54         }
    55     }
    56     for(int i = 1;i<=q;i++)
    57         printf("%I64d
    ",ans[i]);
    58     return 0;
    59 }
    View Code
  • 相关阅读:
    当当网首页——JS代码
    当当网首页——CSS代码
    离散与连续 分度值
    timepicker php strtotime 8hours
    w[wi].disabled = true;
    Browser Cookie Limits
    FROM_UNIXTIME(unix_timestamp), FROM_UNIXTIME(unix_timestamp,format)
    递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。
    从交集角度考虑订房系统的时间连续性
    glup 压缩图片
  • 原文地址:https://www.cnblogs.com/zqy123/p/5746481.html
Copyright © 2011-2022 走看看