codves 4927 線段樹練習5
阿新 • • 發佈:2017-08-31
src 題目 uil ons spa -a 一個 sed desc
有n個數和5種操作
add a b c:把區間[a,b]內的所有數都增加c
set a b c:把區間[a,b]內的所有數都設為c
sum a b:查詢區間[a,b]的區間和
max a b:查詢區間[a,b]的最大值
min a b:查詢區間[a,b]的最小值
輸入描述 Input Description第一行兩個整數n,m,第二行n個整數表示這n個數的初始值
接下來m行操作,同題目描述
輸出描述 Output Description對於所有的sum、max、min詢問,一行輸出一個答案
樣例輸入 Sample Input10 6
3 9 2 8 1 7 5 0 4 6
add 4 9 4
set 2 6 2
add 3 8 2
sum 2 10
max 1 7
min 3 6
樣例輸出 Sample Output
49
11
4
#include<cstring> #include<cstdio> #include<algorithm> #define ll long long using namespace std; const int N=100010; const int inf=0x3f3f3f3f; struct node { ll a_la,s_la,sum,minx,maxx; int l,r,flag; }e[NView Code*8]; int read() { int ans=0,f=1;char c=getchar(); while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();} while(c>=‘0‘&&c<=‘9‘){ans=ans*10+c-48;c=getchar();} return ans*f; } inline void pushup(int ro) { e[ro].sum=e[ro<<1].sum+e[ro<<1|1].sum; e[ro].minx=min(e[ro<<1].minx,e[ro<<1|1].minx); e[ro].maxx=max(e[ro<<1].maxx,e[ro<<1|1].maxx); } void build(int ro,int l,int r) { e[ro].l=l,e[ro].r=r; if(l==r) {int t=read();e[ro].minx=t,e[ro].maxx=t,e[ro].sum=t;} else { int mid=(l+r)>>1; build(ro<<1,l,mid);build(ro<<1|1,mid+1,r);pushup(ro); } return; } inline void down(int ro) { if(e[ro].flag) { e[ro<<1].flag=e[ro<<1|1].flag=1; e[ro].flag=0; int mid=(e[ro].l+e[ro].r)>>1; e[ro<<1].sum=e[ro].s_la*(mid-e[ro].l+1); e[ro<<1|1].sum=e[ro].s_la*(e[ro].r-mid); e[ro<<1].maxx=e[ro<<1].minx=e[ro<<1|1].maxx=e[ro<<1|1].minx=e[ro].s_la; e[ro<<1].s_la=e[ro<<1|1].s_la=e[ro].s_la; e[ro<<1].a_la=e[ro<<1|1].a_la=e[ro].s_la=0; } if(e[ro].a_la) { e[ro<<1].a_la+=e[ro].a_la; e[ro<<1|1].a_la+=e[ro].a_la; e[ro<<1].sum+=e[ro].a_la*(e[ro<<1].r-e[ro<<1].l+1); e[ro<<1].minx+=e[ro].a_la; e[ro<<1].maxx+=e[ro].a_la; e[ro<<1|1].sum+=e[ro].a_la*(e[ro<<1|1].r-e[ro<<1|1].l+1); e[ro<<1|1].minx+=e[ro].a_la; e[ro<<1|1].maxx+=e[ro].a_la; e[ro].a_la=0; } } void add(int ro,int l,int r,int x) { down(ro); if(l<=e[ro].l&&e[ro].r<=r) { if(e[ro].s_la) e[ro].s_la+=x; else e[ro].a_la+=x; e[ro].sum+=x*(e[ro].r-e[ro].l+1); e[ro].maxx+=x; e[ro].minx+=x; return; } int mid=(e[ro].l+e[ro].r)>>1; if(l<=mid) add(ro<<1,l,r,x); if(r>mid) add(ro<<1|1,l,r,x); pushup(ro); return; } void set(int ro,int l,int r,int x) { down(ro); if(l<=e[ro].l&&e[ro].r<=r) { e[ro].sum=x*(e[ro].r-e[ro].l+1); e[ro].minx=x; e[ro].maxx=x; e[ro].a_la=0; e[ro].s_la=x; e[ro].flag=1; return; } int mid=(e[ro].l+e[ro].r)>>1; if(l<=mid) set(ro<<1,l,r,x); if(r>mid) set(ro<<1|1,l,r,x); pushup(ro); return; } ll asum(int ro,int l,int r) { down(ro); if(l<=e[ro].l&&e[ro].r<=r) return e[ro].sum; int mid=(e[ro].l+e[ro].r)>>1; ll ans=0; if(l<=mid) ans+=asum(ro<<1,l,r); if(mid<r) ans+=asum(ro<<1|1,l,r); return ans; } ll amin(int ro,int l,int r) { down(ro); if(l<=e[ro].l&&e[ro].r<=r) return e[ro].minx; int mid=(e[ro].l+e[ro].r)>>1; ll answer=inf; if(l<=mid) answer=min(answer,amin(ro<<1,l,r)); if(mid<r) answer=min(answer,amin(ro<<1|1,l,r)); return answer; } ll amax(int ro,int l,int r) { down(ro); if(l<=e[ro].l&&e[ro].r<=r) return e[ro].maxx; int mid=(e[ro].l+e[ro].r)>>1; ll answer=-inf; if(l<=mid) answer=max(answer,amax(ro<<1,l,r)); if(mid<r) answer=max(answer,amax(ro<<1|1,l,r)); return answer; } int main() { int n,m; n=read(),m=read(); build(1,1,n); //for(int i=1;i<=20;i++) printf("%lld %lld %lld %d %d\n",e[i].sum,e[i].maxx,e[i].minx,e[i].l,e[i].r); for(int i=1;i<=m;i++) { char ch[10]; scanf("%s",ch); if(ch[1]==‘d‘) {int l,r,x;scanf("%d %d %d",&l,&r,&x);add(1,l,r,x);} //for(int i=1;i<=20;i++) printf("%lld %lld %lld %d %d\n",e[i].sum,e[i].maxx,e[i].minx,e[i].l,e[i].r); if(ch[1]==‘e‘) {int l,r,x;scanf("%d %d %d",&l,&r,&x);set(1,l,r,x);} if(ch[1]==‘u‘) {int l,r;scanf("%d %d",&l,&r);printf("%lld\n",asum(1,l,r));} if(ch[1]==‘a‘) {int l,r;scanf("%d %d",&l,&r);printf("%lld\n",amax(1,l,r));} if(ch[1]==‘i‘) {int l,r;scanf("%d %d",&l,&r);printf("%lld\n",amin(1,l,r));} } return 0; }
模板!!!
調了好久。
codves 4927 線段樹練習5