[題意]
有n個氣球,每個氣球有一個顏色x,改變爲y後,美麗值增加|x-y|.
對一個序列有兩種操作:
1. 把區間在[L,R]的顏色染成x.
2. 詢問區間[L,R]的氣球的美麗值總和.
n<=1e5,1<=x<=1e8.
[思路]
區間更新,區間詢問可以聯想到線段樹.
只是更新的時候有點複雜:
因爲一個區間內的顏色不一定相同,無法一次性全部更新,那麼我們就直接更新顏色相同的一塊,把這一個區間都改變.再延遲更新,詢問和更新的時候down下去.
一直一直Wa的原因:
在延遲更新的時候直接記錄的是更新後的顏色,但是,這樣是不行滴:一開始顏色是1,改爲4,再改爲2,答案是5,但是如果直接改成了2,答案就是1了.
當更新的區間越長,更新的時候就會進行地越深,訪問的區間更多;
但更新後的區間的顏色是相同的,那麼就會越有利於下次更新.兩者的制約關係是不會超時的一個因素.
<span style="font-family:Comic Sans MS;font-size:18px;"><span style="font-family:Comic Sans MS;font-size:18px;">#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#define ll long long
using namespace std;
inline void rd(int &res){
res=0;char c;
while(c=getchar(),c<48);
do{
res=(res<<1)+(res<<3)+(c^48);
}while(c=getchar(),c>=48);
}
inline void print(ll k){
if(k==0)return ;
print(k/10);
putchar((k%10)^48);
}
inline void sc(ll k){
print(k);
if(k==0)putchar('0');
putchar('\n');
}
const int M=1e5+5;
int n,m;
struct node{
ll b,c;//b爲美麗值的和,c是顏色差的疊加(用於延遲更新).
int f;//f表示當前的顏色
}T[M*4];
void UP(int p){
T[p].b=T[p<<1].b+T[p<<1|1].b;
if(T[p<<1].f==T[p<<1|1].f&&T[p<<1].f)T[p].f=T[p<<1].f;
else T[p].f=0;
}
void down(int l,int r,int p){
if(T[p].c==0)return ;
int mid=(l+r)>>1;
ll x=T[p].c;
T[p<<1].b+=1ll*(mid-l+1)*x;//[l,mid];
T[p<<1|1].b+=1ll*(r-mid)*x;//[mid+1,r]
T[p<<1|1].f=T[p<<1].f=T[p].f;
T[p<<1].c+=x;T[p<<1|1].c+=x;
T[p].c=0;
}
void build(int l,int r,int p){
T[p].f=0;T[p].c=0;T[p].b=0;
if(l==r){T[p].f=l;return ;}
int mid=(l+r)>>1;
build(l,mid,p<<1);
build(mid+1,r,p<<1|1);
}
void update(int L,int R,int l,int r,int x,int p){
if(L==l&&R==r&&T[p].f){//[l,r]內的顏色更新爲x
T[p].b+=1ll*(r-l+1)*abs(T[p].f-x);//
T[p].c+=abs(T[p].f-x);//答案要疊加
T[p].f=x;
return ;
}
down(L,R,p);
int mid=(L+R)>>1;
if(r<=mid)update(L,mid,l,r,x,p<<1);
else if(l>mid)update(mid+1,R,l,r,x,p<<1|1);
else {update(L,mid,l,mid,x,p<<1);update(mid+1,R,mid+1,r,x,p<<1|1);}
UP(p)//更新完再Up回來
}
ll query(int L,int R,int l,int r,int p){
down(L,R,p);
if(L==l&&R==r)return T[p].b;
int mid=(L+R)>>1;
if(r<=mid)return query(L,mid,l,r,p<<1);
else if(l>mid)return query(mid+1,R,l,r,p<<1|1);
else return query(L,mid,l,mid,p<<1)+query(mid+1,R,mid+1,r,p<<1|1);
}
int main(){
int i,j,k,a,b,c,d;
scanf("%d %d",&n,&m);
build(1,n,1);
for(i=1;i<=m;i++){
rd(a);rd(b);rd(c);
if(a==1){
rd(d);
update(1,n,b,c,d,1);
}
else sc(query(1,n,b,c,1));
}
return 0;
}</span>
20160627離線賽/CodeForces 444C