wikioi 1217

来源:互联网 发布:淘宝内部优惠券qq群号 编辑:程序博客网 时间:2024/04/28 19:25

对线段树成段更新的小小心得:

1、对区间求和时  

a、成段加减

b、成段覆盖

2、对区间求最值

a、成段加减

b、成段替换?还没见过。

下附上第一种情况的代码。

#include <cstdio>#include <algorithm>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int maxn=1000010;long long minn[maxn<<2];long long cov[maxn<<2];void pushup(int rt){minn[rt]=min(minn[rt<<1],minn[rt<<1|1]);}void pushdown(int rt,int m){if(cov[rt]!=0){cov[rt<<1]+=cov[rt]; //此处记住 cov永远为负数;cov[rt<<1|1]+=cov[rt];minn[rt<<1]+=cov[rt];//区别。如果是求最值得话,根值只需要加上懒惰标记即可。
minn[rt<<1|1]+=cov[rt];//但如果是区间求和的话。则需要懒惰标记乘上区间的大小。cov[rt]=0;             }}void build(int l,int r,int rt){cov[rt]=0;if(l==r){scanf("%lld",&minn[rt]);return ;}int m=(l+r)>>1;build(lson);build(rson);pushup(rt);}void update(int L,int R,long long c,int l,int r,int rt){if(L<=l&&r<=R){minn[rt]+=c;  //成段更新了,最值也只变换了C;cov[rt]+=c;  //记录一共变换了多少。所以是加上c; 上同return ;}pushdown(rt,r-l+1);int m=(l+r)>>1;if(L<=m)update(L,R,c,lson);if(R>m)update(L,R,c,rson);pushup(rt);}long long query(int L,int R,int l,int r,int rt){if(L<=l&&r<=R)return minn[rt];pushdown(rt,r-l+1);long long Min=2000000000;int m=(l+r)>>1;if(L<=m)Min=min(Min,query(L,R,lson));if(R>m)Min=min(Min,query(L,R,rson));return Min;}int main(){int n,m;scanf("%d %d",&n,&m);build(1,n,1);for(int i=1;i<=m;i++){long long c;int l,r;scanf("%lld %d %d",&c,&l,&r);update(l,r,-c,1,n,1);long long k=query(l,r,1,n,1);//printf("\n%lld\n\n",k);if(k<0){printf("-1\n%d\n",i);return 0;}}printf("0\n");return 0;}


成段加减

void pushdown(int rt,int m){if(cov[rt]!=0){cov[rt<<1]+=cov[rt]; cov[rt<<1|1]+=cov[rt];sum[rt<<1]+=cov[rt]*(m-(m>>1));sum[rt<<1|1]+=cov[rt]*(m>>1);cov[rt]=0;}}void update(int L,int R,long long c,int l,int r,int rt){if(L<=l&&r<=R){sum[rt]+=c*(r-l+1);  //需要加减;cov[rt]+=c;//这里也是。上同。return ;}pushdown(rt,r-l+1);int m=(l+r)>>1;if(L<=m)update(L,R,c,lson);if(R>m)update(L,R,c,rson);pushup(rt);}


成段更新


void pushdown(int rt,int m){if(cov[rt]!=0){cov[rt<<1]=cov[rt]; cov[rt<<1|1]=cov[rt];sum[rt<<1]=cov[rt]*(m-(m>>1));sum[rt<<1|1]=cov[rt]*(m>>1);cov[rt]=0;}}void update(int L,int R,long long c,int l,int r,int rt){if(L<=l&&r<=R){sum[rt]=c*(r-l+1);//一共多大。cov[rt]=c;  //直接覆盖掉。上同。return ;}pushdown(rt,r-l+1);int m=(l+r)>>1;if(L<=m)update(L,R,c,lson);if(R>m)update(L,R,c,rson);pushup(rt);}




0 0