POJ 3468 线段树+状压

题意:给你n个数,有对区间的加减操作,问某个区间的和是多少。
思路:状压+线段树(要用lazy标记,否则会TLE)

//By SiriusRen
#include <cstdio>
#include <cstring>
#define N 100001
using namespace std;
long long tree[N*4],lazy[N*4];
int xx,yy,zz,n,q;
char jy;
void push_down(int pos,int num){
    lazy[pos*2]+=lazy[pos],lazy[pos*2+1]+=lazy[pos];
    tree[pos*2]+=(num-num/2)*lazy[pos],tree[pos*2+1]+=(num/2)*lazy[pos];
    lazy[pos]=0;
}
void build(int l,int r,int pos){
    if(l==r){scanf("%lld",&tree[pos]);return;}
    int mid=(l+r)/2;
    build(l,mid,pos*2),build(mid+1,r,pos*2+1);
    tree[pos]=tree[pos*2]+tree[pos*2+1];
}
void add(int l,int r,int pos){
    if(l>=xx&&r<=yy){lazy[pos]+=zz;tree[pos]+=(long long)(r-l+1)*zz;return;}
    if(lazy[pos])push_down(pos,r-l+1);
    int mid=(l+r)/2;
    if(mid>=xx)add(l,mid,pos*2);
    if(mid<yy)add(mid+1,r,pos*2+1);
    tree[pos]=tree[pos*2]+tree[pos*2+1];
}
long long query(int l,int r,int pos){
    if(l>=xx&&r<=yy)return tree[pos];
    if(lazy[pos])push_down(pos,r-l+1);
    int mid=(l+r)/2;
    if(mid<xx)return query(mid+1,r,pos*2+1);
    else if(mid>=yy)return query(l,mid,pos*2);
    else return query(l,mid,pos*2)+query(mid+1,r,pos*2+1);
}
int main(){
    scanf("%d%d",&n,&q);
    build(1,n,1);
    while(q--){
        scanf("
%c%d%d",&jy,&xx,&yy);
        if(jy=='C')scanf("%d",&zz),add(1,n,1);
        else printf("%lld
",query(1,n,1));
    }
}

这里写图片描述

原文地址:https://www.cnblogs.com/SiriusRen/p/6532436.html