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!

 

转载于:https://www.cnblogs.com/Alan-Luo/p/10191961.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值