1. 程式人生 > >codves 4927 線段樹練習5

codves 4927 線段樹練習5

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 Input

10 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[N
*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; }
View Code

模板!!!

調了好久。

codves 4927 線段樹練習5