1. 程式人生 > >BZOJ 4695 最假女選手 線段樹

BZOJ 4695 最假女選手 線段樹

題意:

  給定一個長度為 N序列,編號從1 到 N。要求支援下面幾種操作:

  1.給一個區間[L,R] 加上一個數x    2.把一個區間[L,R] 裡小於x 的數變成x    3.把一個區間[L,R] 裡大於x 的數變成x    4.求區間[L,R] 的和   5.求區間[L,R] 的最大值   6.求區間[L,R] 的最小值  

分析:

  你聽說過Segment Tree Beats麼?

  快去看一看吧。這題居然才只有六個操作,真的是重口難調啊。

  思想還是不難的,這裡就不粘課件了。

  由於這題擁有著比較玄學的空間限制和比較玄學的資料範圍,所以可能需要試探很多遍才能不MLE。

  (如果你是指標線段樹我也沒啥可說的)

  程式碼是我修改抄襲一位大神的,予以美化(好像更難讀了),以便於非指標使用者食用。

程式碼:

  1 #include<bits/stdc++.h>
  2 #define ll long long
  3 using namespace std;
  4 const int N=3.7e5+5,inf=1e9;
  5 struct node{
  6     int l,r,ls,rs,mnc,mxc;//標號為1代表最值
7 ll mn1,mn2,mx1,mx2;//,為2代表次值 8 ll lmn,lmx,lad,s;//c代表的是count數量,不是次 9 }t[N<<2];int cnt=0,rt,n,m,x; 10 char readchar(){ 11 static char buf[100000],*l=buf,*r=buf; 12 if(l==r) r=(l=buf)+fread(buf,1,100000,stdin); 13 if(l==r) return EOF;return *l++;} 14 int read(){ 15 int x=0
,f=1;char ch=readchar(); 16 while(ch<'0'||ch>'9'){if(ch=='-') f=-f;ch=readchar();} 17 while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=readchar();}; 18 return x*f; 19 } void pushup(int cur){ 20 int ls=t[cur].ls,rs=t[cur].rs; 21 t[cur].s=t[ls].s+t[rs].s; 22 if(t[ls].mn1<t[rs].mn1) 23 t[cur].mn1=t[ls].mn1, 24 t[cur].mnc=t[ls].mnc, 25 t[cur].mn2=min(t[ls].mn2,t[rs].mn1); 26 else if(t[ls].mn1>t[rs].mn1) 27 t[cur].mn1=t[rs].mn1, 28 t[cur].mnc=t[rs].mnc, 29 t[cur].mn2=min(t[rs].mn2,t[ls].mn1); 30 else t[cur].mn1=t[ls].mn1, 31 t[cur].mnc=t[ls].mnc+t[rs].mnc, 32 t[cur].mn2=min(t[ls].mn2,t[rs].mn2); 33 if(t[ls].mx1>t[rs].mx1) 34 t[cur].mx1=t[ls].mx1, 35 t[cur].mxc=t[ls].mxc, 36 t[cur].mx2=max(t[ls].mx2,t[rs].mx1); 37 else if(t[ls].mx1<t[rs].mx1) 38 t[cur].mx1=t[rs].mx1, 39 t[cur].mxc=t[rs].mxc, 40 t[cur].mx2=max(t[rs].mx2,t[ls].mx1); 41 else t[cur].mx1=t[ls].mx1, 42 t[cur].mxc=t[ls].mxc+t[rs].mxc, 43 t[cur].mx2=max(t[ls].mx2,t[rs].mx2); 44 } void adsm(int cur,ll x){ 45 t[cur].mn1+=x;t[cur].mx1+=x; 46 if(t[cur].mn2!= inf) t[cur].mn2+=x; 47 if(t[cur].mx2!=-inf) t[cur].mx2+=x; 48 t[cur].s+=x*(t[cur].r-t[cur].l+1); 49 t[cur].lad+=x;return ; 50 } void admn(int cur,ll x){ 51 if(t[cur].mn1==t[cur].mx1) t[cur].mx1+=x; 52 if(t[cur].mn1==t[cur].mx2) t[cur].mx2+=x; 53 t[cur].lmn+=x;t[cur].mn1+=x; 54 t[cur].s+=x*t[cur].mnc;return ; 55 } void admx(int cur,ll x){ 56 if(t[cur].mn1==t[cur].mx1) t[cur].mn1+=x; 57 if(t[cur].mx1==t[cur].mn2) t[cur].mn2+=x; 58 t[cur].mx1+=x;t[cur].lmx+=x; 59 t[cur].s+=x*t[cur].mxc;return ; 60 } void pushdown(int cur){ 61 int ls=t[cur].ls,rs=t[cur].rs; 62 if(t[cur].lad) adsm(ls,t[cur].lad), 63 adsm(rs,t[cur].lad),t[cur].lad=0; 64 if(t[cur].lmn){ 65 if(t[ls].mn1<=t[rs].mn1) 66 admn(ls,t[cur].lmn); 67 if(t[ls].mn1>=t[rs].mn1) 68 admn(rs,t[cur].lmn);t[cur].lmn=0; 69 } if(t[cur].lmx){ 70 if(t[ls].mx1>=t[rs].mx1) 71 admx(ls,t[cur].lmx); 72 if(t[ls].mx1<=t[rs].mx1) 73 admx(rs,t[cur].lmx);t[cur].lmx=0; 74 } return ; 75 } void build(int l,int r,int cur){ 76 t[cur].l=l,t[cur].r=r; 77 if(l==r){ t[cur].mxc=1; 78 t[cur].ls=t[cur].rs=-1;t[cur].mnc=1; 79 t[cur].lmn=t[cur].lmx=t[cur].lad=0; 80 t[cur].s=t[cur].mx1=t[cur].mn1=read(); 81 t[cur].mn2=inf;t[cur].mx2=-inf;return ; 82 } int mid=l+r>>1; 83 t[cur].ls=cnt++;t[cur].rs=cnt++; 84 build(l,mid,t[cur].ls); 85 build(mid+1,r,t[cur].rs); 86 pushup(cur);return ; 87 } 88 #define sum(x,y) x+y; 89 #define upd(fun,lm,req,tag) \ 90 void fun(int l,int r,int cur){ \ 91 if(lm) return ; \ 92 if(l<=t[cur].l&&t[cur].r<=r&&req) \ 93 {tag;return ;} pushdown(cur); \ 94 int mid=t[cur].l+t[cur].r>>1; \ 95 if(l<=mid) fun(l,r,t[cur].ls); \ 96 if(mid<r) fun(l,r,t[cur].rs); \ 97 pushup(cur);return ; \ 98 } 99 #define qry(fun,typ,ret,op) \ 100 typ fun(int l,int r,int cur){ \ 101 int ls=t[cur].ls,rs=t[cur].rs; \ 102 if(l<=t[cur].l&&t[cur].r<=r) return ret;\ 103 pushdown(cur); \ 104 int mid=t[cur].l+t[cur].r>>1; \ 105 if(r<=mid) return fun(l,r,ls); \ 106 if(mid<l) return fun(l,r,rs); \ 107 return op(fun(l,r,ls),fun(l,r,rs)); \ 108 } 109 upd(uad,0,1,adsm(cur,x)) 110 upd(umn,t[cur].mn1>=x,t[cur].mn2>x, 111 admn(cur,x-t[cur].mn1)) 112 upd(umx,t[cur].mx1<=x,t[cur].mx2<x, 113 admx(cur,x-t[cur].mx1)) 114 qry(qsm,ll,t[cur].s,sum) 115 qry(qmx,ll,t[cur].mx1,max) 116 qry(qmn,ll,t[cur].mn1,min) 117 signed main(){ 118 rt=cnt++;n=read(); 119 build(1,n,rt);m=read(); 120 for(int l,r,op;m--;){ 121 op=read();l=read();r=read(); 122 if(op<=3) x=read(); 123 if(op==1) uad(l,r,rt); 124 if(op==2) umn(l,r,rt); 125 if(op==3) umx(l,r,rt); 126 if(op==4) printf("%lld\n",qsm(l,r,rt)); 127 if(op==5) printf("%lld\n",qmx(l,r,rt)); 128 if(op==6) printf("%lld\n",qmn(l,r,rt)); 129 } return 0; 130 }
Segment Tree Beats!