標籤:blog color os 2014 問題 for
題目大意:
1 l r x操作 講 [l,r]上的節點塗成x顏色,並且每個節點的值都加上 |y-x| y為塗之前的顏色
2 l r 操作,求出[l,r]上的和。
思路分析:
如果一個區間為相同的顏色。那麼我們才可以合併作業。
所以我們之前找相同的區間就好。
但是問題是如何合併作業。
那麼我們定義一個val 表示這個區間每個位置上應該加上的值。
pushdown 的時候這個值是可以相加的。
#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#define maxn 100005#define lson num<<1,s,mid#define rson num<<1|1,mid+1,eusing namespace std;typedef long long LL;LL color[maxn<<2];LL sum[maxn<<2];LL val[maxn<<2];LL Abs(LL x){ return x>0?x:-x;}void pushdown(int num,int s,int e){ if(color[num]!=-1) { int mid=(s+e)>>1; sum[num<<1]+=val[num]*(mid-s+1); sum[num<<1|1]+=val[num]*(e-mid); val[num<<1]+=val[num]; val[num<<1|1]+=val[num]; color[num<<1]=color[num<<1|1]=color[num]; color[num]=-1; val[num]=0; }}void pushup(int num){ if(color[num<<1]==color[num<<1|1]) color[num]=color[num<<1]; else color[num]=-1; sum[num]=sum[num<<1]+sum[num<<1|1];}void build(int num,int s,int e){ sum[num]=0; val[num]=0; color[num]=-1; if(s==e) { color[num]=s; return; } int mid=(s+e)>>1; build(lson); build(rson);}void update(int num,int s,int e,int l,int r,LL v){ if(l<=s && r>=e) { if(color[num]!=-1) { sum[num]+=(LL)Abs(v-color[num])*(e-s+1); val[num]+=Abs(color[num]-v); color[num]=v; return; } } int mid=(s+e)>>1; pushdown(num,s,e); if(l<=mid)update(lson,l,r,v); if(r>mid)update(rson,l,r,v); pushup(num);}LL query(int num,int s,int e,int l,int r){ if(l<=s && r>=e) { return sum[num]; } int mid=(s+e)>>1; pushdown(num,s,e); if(r<=mid)return query(lson,l,r); else if(l>mid)return query(rson,l,r); else return query(lson,l,mid)+query(rson,mid+1,r);}int main(){ int n,m; scanf("%d%d",&n,&m); build(1,1,n); while(m--) { int type; scanf("%d",&type); if(type==1){ int l,r; LL x; scanf("%d%d%I64d",&l,&r,&x); update(1,1,n,l,r,x); } else { int l,r; scanf("%d%d",&l,&r); printf("%I64d\n",query(1,1,n,l,r)); } } return 0;}/*10 101 5 9 62 6 101 1 9 31 3 10 52 4 6*/