HDU 5828(线段树)

Problem Rikka with Sequence

题目大意

  维护一个序列,支持三种操作。

  操作1:区间加。  操作二:区间开根号(向下取整)。  操作3:区间求和。

解题分析

  可以发现经过若干次操作后,整些区间内的数会趋向于相同。

  可以再开一个标记,表示这个区间内的数是否相同,这样可以优化一下区间开根号的复杂度。

  然后就卡过去了~~

  Pushdown的时候要注意不要把一个lazy标记往下传两次。

参考程序

  1 #include <cstdio>
  2 #include <cmath>
  3 
  4 #define maxn 200008
  5 #define lson l , m , rt << 1
  6 #define rson m+1 , r , rt << 1 | 1
  7 #define eps 1e-8
  8 long long sum[maxn << 2],lazy[maxn << 2];
  9 long long tag[maxn << 2];
 10 int n;
 11 
 12 void Pushup(int rt){
 13     sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
 14     if (tag[rt << 1] == tag[rt << 1 | 1]) tag[rt]=tag[rt << 1]; else tag[rt] = 0;
 15 }
 16 
 17 void Pushdown(int rt,int m){
 18     if (tag[rt]){
 19         tag[rt << 1] = tag[rt];
 20         tag[rt << 1 | 1] = tag[rt];
 21         sum[rt << 1] = tag[rt] * (m-m/2);
 22         sum[rt << 1 | 1] = tag[rt] * (m/2);
 23         lazy[rt]=0;
 24     }
 25     if (lazy[rt]) {
 26         lazy[rt << 1] += lazy[rt];
 27         lazy[rt << 1 | 1] += lazy[rt];
 28         sum[rt << 1] += lazy[rt] * (m - m / 2);
 29         sum[rt << 1 | 1] += lazy[rt] * (m / 2);
 30         if (tag[rt << 1]) tag[rt << 1] += lazy[rt];
 31         if (tag[rt << 1 | 1]) tag[rt << 1 | 1] += lazy[rt];
 32         lazy[rt] = 0;
 33     }
 34 }
 35 
 36 void Build(int l,int r,int rt){
 37     lazy[rt] = 0;
 38     tag[rt] = 0;
 39     if (l==r) {
 40         scanf("%d",&sum[rt]);
 41         tag[rt]=sum[rt]; 
 42         return;
 43     }
 44     int m = (l + r) >> 1;
 45     Build(lson);
 46     Build(rson);
 47     Pushup(rt);
 48 }
 49 
 50 void Update(int L,int R,int val,int l,int r,int rt){
 51     if (L <= l && r <= R) {
 52         sum[rt] += 1ll*(r - l + 1) * val;
 53         lazy[rt] += val;
 54         if (tag[rt]) tag[rt]+=val;
 55         return;
 56     }
 57     Pushdown(rt,r - l + 1);
 58     int m = (l + r) >> 1;
 59     if (L <= m) Update(L,R,val,lson);
 60     if (m <  R) Update(L,R,val,rson);
 61     Pushup(rt);
 62 }
 63 
 64 void Update_2(int L,int R,int l,int r,int rt){
 65     if (L<=l && r<=R && tag[rt]){
 66         tag[rt] = (long long)(sqrt(tag[rt])+eps);
 67         sum[rt] = 1ll*tag[rt] * (r - l + 1);
 68         return;
 69     }
 70     Pushdown(rt,r - l + 1);
 71     int m = (l + r) >> 1;
 72     if (L <= m) Update_2(L,R,lson);
 73     if (m <  R) Update_2(L,R,rson);
 74     Pushup(rt);
 75 }
 76 
 77 long long Query(int L,int R,int l,int r,int rt){
 78     if (L <= l && r <= R) {
 79         return sum[rt];
 80     }
 81     Pushdown(rt,r - l + 1);
 82     int m = (l + r) >> 1;
 83     long long res = 0;
 84     if (L <= m) res += Query(L,R,lson);
 85     if (m <  R) res += Query(L,R,rson);
 86     return res;
 87 }
 88 
 89 
 90 int main() {
 91     int T;
 92     scanf("%d",&T);
 93     while (T--){
 94         int Q;
 95         scanf("%d %d",&n,&Q);
 96         Build(1,n,1);
 97         while (Q--) {
 98             int x,y,z,w;
 99             scanf("%d",&w);
100             if (w==1) {
101                 scanf("%d%d%d",&x,&y,&z);
102                 Update(x,y,z,1,n,1);
103             }
104             if (w==2){
105                 scanf("%d%d",&x,&y);
106                 Update_2(x,y,1,n,1);
107             }
108             if (w==3){
109                 scanf("%d%d",&x,&y);
110                 printf("%I64d\n",Query(x,y,1,n,1));                
111             }
112         }
113     }
114 }
View Code

 

posted @ 2016-08-11 19:15  rpSebastian  阅读(735)  评论(0编辑  收藏  举报