Hdu5828-Rikka with Sequence(线段树区间开方)

写在前面
ldx神犇今讲线段树,然后就涉及到了本题目的一个骚操作。

传送门
Solution
注意到本题实际上要求的是区间加,区间求和,区间开根号。前两个是常规操作,学了都会,然而怎样开根号?显然我们应该暴力修改开方这个操作本身进行考虑。那么注意到,开一次方,一个序列中的每个数逐步接近其他的数,所以说我们可以考虑这么干:对序列维护一个最大值与最小值,如果说他们开方以后最大值减去最小值的差大于1,那么我们就认为这些数还不够接近,所以说直接递归修改这些区间,如果说这个差小于等于1,那么我们就继续暴力讨论一下。如果说这个差等于0,那么区间开方操作就相当于一次区间覆盖操作,这是常规操作,如果大于0小于等于1,那么可以看作一次区间减操作,这也很常规,那么这样我们就把题目分析完了。

代码如下

  1 #include
  2 using namespace std;
  3 #define N 100010
  4 #define lc (p<<1)
  5 #define rc (p<<1|1)
  6 #define mid (T[p].l+T[p].r>>1)
  7 typedef long long ll;
  8 ll read(){
  9     ll sum=0,neg=1;
 10     char c=getchar();
 11     while(c>'9'||c<'0'&&c!='-') c=getchar();
 12     if(c=='-') neg=-1,c=getchar();
 13     while(c>='0'&&c<='9') sum=(sum<<1)+(sum<<3)+c-'0',c=getchar();
 14     return sum*neg;
 15 }
 16 ll n,m,T,a[N];
 17 struct Node{
 18     int l,r;
 19     ll sum,minn,maxn,lazy,tag;
 20 };
 21 struct SegmentTree{
 22     Node T[N*4];
 23     void pushup(int p){
 24         T[p].maxn=max(T[lc].maxn,T[rc].maxn);
 25         T[p].minn=min(T[lc].minn,T[rc].minn);
 26         T[p].sum=T[lc].sum+T[rc].sum;
 27     }
 28     void pushnow(int p,ll v){
 29         T[p].sum+=(T[p].r-T[p].l+1)*v;
 30         T[p].lazy+=v;
 31         T[p].maxn+=v;
 32         T[p].minn+=v;
 33     }
 34     void pushcover(int p,ll v){
 35         T[p].lazy=0;
 36         T[p].sum=(T[p].r-T[p].l+1)*v;
 37         T[p].tag=T[p].maxn=T[p].minn=v;
 38     }
 39     void pushdown(int p){
 40         if(T[p].tag!=-1){
 41             pushcover(lc,T[p].tag);
 42             pushcover(rc,T[p].tag);
 43             T[p].tag=-1;
 44         }
 45         if(T[p].lazy){
 46             pushnow(lc,T[p].lazy);
 47             pushnow(rc,T[p].lazy);
 48             T[p].lazy=0;
 49         }
 50     }
 51     void build(int p,int l,int r){
 52         T[p].l=l; T[p].r=r; T[p].lazy=0; T[p].tag=-1;
 53         if(l==r){
 54             T[p].maxn=T[p].minn=T[p].sum=a[l];
 55             return;
 56         }
 57         build(lc,l,mid);
 58         build(rc,mid+1,r);
 59         pushup(p);
 60     }
 61     void update(int p,int ql,int qr,ll v){
 62         if(ql>T[p].r||qrreturn;
 63         if(ql<=T[p].l&&T[p].r<=qr){
 64             pushnow(p,v);
 65             return;
 66         }
 67         pushdown(p);
 68         if(qr<=mid) update(lc,ql,qr,v);
 69         else if(ql>mid) update(rc,ql,qr,v);
 70         else update(lc,ql,mid,v),update(rc,mid+1,qr,v);
 71         pushup(p);
 72     }
 73     void modify(int p,int ql,int qr){
 74         if(ql>T[p].r||qrreturn;
 75         if(ql<=T[p].l&&T[p].r<=qr&&T[p].maxn-T[p].minn<=1){
 76             ll fx=sqrt(T[p].maxn),fy=sqrt(T[p].minn);
 77             if(fx==fy) pushcover(p,fx);
 78             else pushnow(p,fx-T[p].maxn);
 79             return;
 80         }
 81         pushdown(p);
 82         if(qr<=mid)modify(lc,ql,qr);
 83         else if(ql>mid)modify(rc,ql,qr);
 84         else modify(lc,ql,mid),modify(rc,mid+1,qr);
 85         pushup(p);
 86     }
 87     ll query(int p,int ql,int qr){
 88         if(ql>T[p].r||qrreturn 0;
 89         if(ql<=T[p].l&&T[p].r<=qr) return T[p].sum;
 90         pushdown(p);
 91         if(qr<=mid) return query(lc,ql,qr);
 92         if(ql>mid) return query(rc,ql,qr);
 93         return query(lc,ql,mid)+query(rc,mid+1,qr);
 94     }
 95 }Tree;
 96 int main(){
 97     T=read();
 98     while(T--){
 99         n=read(); m=read();
100         for(int i=1;i<=n;i++) a[i]=read();
101         Tree.build(1,1,n);
102         while(m--){
103             int opt,l,r;
104             opt=read(); l=read(); r=read();
105             switch(opt){
106                 case 1:{
107                     ll v=read();
108                     Tree.update(1,l,r,v);
109                     break;
110                 }
111                 case 2:{
112                     Tree.modify(1,l,r);
113                     break;
114                 }
115                 default:{
116                     printf("%lld\n",Tree.query(1,l,r));
117                     break;
118                 }
119             }
120         }
121     }
122     return 0;
123 }
View Code

 

转载于:https://www.cnblogs.com/Neonen/p/9832659.html

你可能感兴趣的:(Hdu5828-Rikka with Sequence(线段树区间开方))