zoukankan      html  css  js  c++  java
  • codeforces 295E Yaroslav and Points (离线操作+离散化+区间合并)

    参考链接:http://blog.csdn.net/dyx404514/article/details/8817717

    写的很详细,这里就不再赘述,附上我的代码。

    #include <iostream>
    #include <stdio.h>
    #include <algorithm>
    #define lson rt<<1,L,mid
    #define rson rt<<1|1,mid+1,R
    /*
    AC
    http://blog.csdn.net/dyx404514/article/details/8817717
    */
    using namespace std;
    const int maxn=100005;
    int n,m;
    int nn;  //最后离散后的点的个数
    long long val[maxn*2];  //存储所有数据
    long long hashval[maxn*2];  //存储离散后的数据
    long long a[maxn],aa[maxn]; //存储初始序列
    int pos[maxn];  //存储初始序列在hashval中的位置
    int cnt=-1;  //用于离散时,统计总共有多少个数
    int idx=1;   //用于建树时,获取初始的n个坐标值在hashval中位置的索引
    struct Node{
        int num;  //该区间有多少个点。
        long long sum;    //该区间点的横坐标之和。
        long long ans;    //该区间每一对点的距离之和。
    }tree[maxn<<3];
    
    struct Query{
        int t,p,d;
        long long l,r;
    }q[maxn];
    
    /*
    注意:这里二分查找时,用mark标记是查找>=m的数的位置,还是查找<=m的数的位置。
    当更新的时候,mark=2即可。
    当查询时,查找l的时候,由于l可能不存在,所以我们查找的时候需要查找>=l的最近的数的位置,此时mark=1;
              查找r的时候,由于r可能不存在,所以我们查找的时候需要查找<=r的最近的数的位置,此时mark=2
    */
    int binarySearch(long long m,int mark,int length){
        int l=0,r=length+1,mid;
        while(r-l>1){
            mid=(l+r)>>1;
            if(hashval[mid]<=m)
                l=mid;
            else
                r=mid;
        }
        if(hashval[l]==m)
            return l;
        if(mark==1)
            return l+1;
        else
            return l;
    }
    
    void pushUp(Node &rt,Node &ls,Node &rs){
        rt.num=ls.num+rs.num;
        rt.sum=ls.sum+rs.sum;
        rt.ans=ls.num*rs.sum-rs.num*ls.sum+ls.ans+rs.ans;  //公式的话,很容易就能推出,这里就不详细说了
    }
    void build(int rt,int L,int R){
        if(L==R){
            tree[rt].num=tree[rt].sum=tree[rt].ans=0;
            if(idx<=n && L==pos[idx]){
                tree[rt].num=1;
                tree[rt].sum=aa[idx];
                tree[rt].ans=0;
                idx++;
            }
            return;
        }
        int mid=(L+R)>>1;
        build(lson);
        build(rson);
        pushUp(tree[rt],tree[rt<<1],tree[rt<<1|1]);
    }
    /*
    op=1即是加入一个数
    op=0即使去除一个数
    */
    void update(int rt,int L,int R,int x,int op,int val){
        if(L==R){
            if(op==1){
                tree[rt].num=1;
                tree[rt].sum=val;
                tree[rt].ans=0;
            }
            else{
                tree[rt].num=tree[rt].sum=tree[rt].ans=0;
            }
            return;
        }
        int mid=(L+R)>>1;
        if(x<=mid)
            update(lson,x,op,val);
        else
            update(rson,x,op,val);
        pushUp(tree[rt],tree[rt<<1],tree[rt<<1|1]);
    }
    Node query(int rt,int L,int R,int l,int r){
        if(l<=L&&R<=r){
            return tree[rt];
        }
        Node tmp,a,b;
        int mid=(L+R)>>1;
        if(r<=mid)
            tmp=query(lson,l,r);
        else if(l>mid)
            tmp=query(rson,l,r);
        else{
            a=query(lson,l,mid);
            b=query(rson,mid+1,r);
            pushUp(tmp,a,b);
        }
        return tmp;
    }
    int main()
    {
        int v,t,p,d;
        int x,y;
        long long l,r;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&v);
            a[i]=v;
            aa[i]=v;
            val[++cnt]=v;
        }
        scanf("%d",&m);
        for(int i=1;i<=m;i++){
            scanf("%d",&t);
            if(t==1){
                scanf("%d%d",&p,&d);
                q[i].t=t;
                q[i].p=p;
                q[i].d=d;
                aa[p]+=d; //是累加的
                val[++cnt]=aa[p];
            }
            else{
                scanf("%I64d%I64d",&l,&r);
                q[i].t=t;
                q[i].l=l;  //也可以将查询的l和r加入到离散的数据中去,这样二分查找的时候就不用考虑l和r不存在的问题,
                q[i].r=r;  //查找时,当hashval[mid]==m时返回mid就行,当然这样数组相对就要开大了。
            }
        }
        sort(val,val+cnt+1);
    //for(int i=0;i<=cnt;i++)
    //   printf("%I64d  ",val[i]);
    //printf("
    ");
    
        nn=0;
        hashval[++nn]=val[0];
        for(int i=1;i<=cnt;i++){
            if(val[i]!=val[i-1]){
                hashval[++nn]=val[i];
            }
        }
    //for(int i=1;i<=nn;i++)
    //    printf("%I64d  ",hashval[i]);
    //printf("
    ");
    
        for(int i=1;i<=n;i++)
            aa[i]=a[i];
        sort(aa+1,aa+n+1);
    
    //这里pos数组存储的是初始序列在离散后的数组hashval中的位置,用于建树的初始化
    //也可以不采用该方法,在建树时都设为0,然后在对初始序列一个个update即可
        for(int i=1;i<=n;i++){
            pos[i]=binarySearch(aa[i],2,nn);
        }
    
        build(1,1,nn);
        for(int i=1;i<=m;i++){
            if(q[i].t==1){
                x=binarySearch(a[q[i].p],2,nn);
                update(1,1,nn,x,0,1);
                a[q[i].p]+=q[i].d;
                x=binarySearch(a[q[i].p],2,nn);
                update(1,1,nn,x,1,a[q[i].p]);
            }
            else{
                x=binarySearch(q[i].l,1,nn);
                y=binarySearch(q[i].r,2,nn);
    //printf("%I64d %I64d  %d %d
    ",q[i].l,q[i].r,x,y);
                if(x>nn||y<1||x>y)
                    printf("0
    ");  //可能会遇到l>r的情况,参见代码后面的例子
                else
                    printf("%I64d
    ",query(1,1,nn,x,y).ans);
            }
        }
        return 0;
    }
    
    /*
    4
    20 30 10 -20
    5           x  y
    2 -25 -20   2  2
    1 2 -40
    2 21 25     6  5 (这里l>r,一开始忽略了这种情况,导致运行到第二个程序的时候,查询一直往下,无法停止,导致MLE)
    1 4 -10
    2 -35 -30   1  1
    
    附:叶子节点对应的数据:
    -30 -20 -10 10 20 30
    */
  • 相关阅读:
    Django中实现加载渲染模版
    【干货】批量文件合拼 cat 命令的使用
    【Sql】获取数据库字段信息
    【C#】 TxtHelper
    【Css】鼠标
    【HTTP】H5唤醒支付宝
    【dotnet】程序集注入
    【OpenXml】excel 导入导出
    一、API​​网关
    【kafka】二、kafka的基本概念
  • 原文地址:https://www.cnblogs.com/chenxiwenruo/p/3426026.html
Copyright © 2011-2022 走看看