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("\n");
    return 0;
}

 

posted @ 2013-11-12 21:06  辰曦~文若  阅读(350)  评论(0编辑  收藏  举报