• CF 295A Greg and Array (两次建树,区间更新,单点查询)


    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #define lson rt<<1,L,mid
    #define rson rt<<1|1,mid+1,R
    /*
    题意:给出原始序列a[1],a[2],...a[n]
          给出m个操作方式 l r d,把a[l],...a[r]都加上d
          然后给出k个操作  x  y  执行第x到第y个操作
    
    思路:如果直接执行k个对应的x~y操作,会超时的。
          所以,我们需要统计一下对于m个操作,每个操作需要统计多少次,然后每个操作执行一次即可。
          这样就先建立一颗树,查询k次[x,y],最后再单点查询,得到第i个操作需要执行的次数cnt[i]。
          然后在建立一次(因为操作都一样,所以用同一棵树即可),这次分别对m个操作进行更新,
          更新值为cnt[i]*di,再单点更新得出最后的a[i]。
    */
    using namespace std;
    const int maxn=100005;
    int n,m,k;
    long long a[maxn];  //原始序列
    long long cnt[maxn];  //cnt[i]表示第i个操作方式需要执行的次数
    struct Node{
        long long add;
        bool lazy;
    }tree[maxn<<2];
    
    struct Operation{
        int l,r;
        long long d;
    }op[maxn];
    
    void build(int rt,int L,int R){
        tree[rt].add=0;
        tree[rt].lazy=false;
        if(L==R)
            return;
        int mid=(L+R)>>1;
        build(lson);
        build(rson);
    }
    
    void pushDown(int rt){
        if(tree[rt].lazy){
            tree[rt<<1].add+=tree[rt].add;
            tree[rt<<1|1].add+=tree[rt].add;
            tree[rt<<1].lazy=tree[rt<<1|1].lazy=true;
            tree[rt].add=0;
            tree[rt].lazy=false;
        }
    }
    void update(int rt,int L,int R,int l,int r,long long val){
        if(l<=L&&R<=r){
            tree[rt].add+=val;
            tree[rt].lazy=true;
            return;
        }
        pushDown(rt);
        int mid=(L+R)>>1;
        if(l<=mid)
            update(lson,l,r,val);
        if(r>mid)
            update(rson,l,r,val);
    }
    
    //单点查询cnt
    void query1(int rt,int L,int R){
        if(L==R){
            cnt[L]+=tree[rt].add;
            return;
        }
        pushDown(rt);
        int mid=(L+R)>>1;
        query1(lson);
        query1(rson);
    }
    //单点查询a
    void query2(int rt,int L,int R){
        if(L==R){
            a[L]+=tree[rt].add;
            return;
        }
        pushDown(rt);
        int mid=(L+R)>>1;
        query2(lson);
        query2(rson);
    }
    int main()
    {
        int x,y;
        scanf("%d%d%d",&n,&m,&k);
    
        for(int i=1;i<=n;i++){
            scanf("%I64d",&a[i]);
        }
        for(int i=1;i<=m;i++){
            scanf("%d%d%I64d",&op[i].l,&op[i].r,&op[i].d);
        }
        //先对m个操作方式建树,统计每个操作方式需要执行的次数
        build(1,1,m);
        for(int i=1;i<=k;i++){
            scanf("%d%d",&x,&y);
            update(1,1,m,x,y,1);
    
        }
        memset(cnt,0,sizeof(cnt));
        query1(1,1,m);
    
        //再对n个数建树,更新所增加的值
        build(1,1,n);
        for(int i=1;i<=m;i++){
            update(1,1,n,op[i].l,op[i].r,op[i].d*cnt[i]);  //对每个操作只要查询一次即可
        }
        query2(1,1,n);
        flag=true;
        for(int i=1;i<=n;i++){
            if(flag){
                printf("%I64d",a[i]);
                flag=false;
            }
            else
                printf(" %I64d",a[i]);
        }
        printf("
    ");
        return 0;
    }
  • 相关阅读:
    多线程ExecutorService 的理解与使用
    MySql索引
    HttpURLConnection和HttpClient使用
    httpclient调用接口
    几个linux命令
    面试之自定义字符串操作
    C和C++中struct的区别
    如何根据端口号查看占用进程
    linux和window如何发布服务
    MYSQL中GROUP_CONCAT和CONCAT函数配合使用
  • 原文地址:https://www.cnblogs.com/chenxiwenruo/p/3420238.html
Copyright © 2020-2023  润新知