hdu 4267 A Simple Problem with Integers (线段树)

 

 

 转自:

 

题目:给出n个数,每次将一段区间内满足(i-l)%k==0  (r>=i>=l) 的数ai增加c

http://acm.hdu.edu.cn/showproblem.php?pid=4267 

比较容易往线段树上想的。但是由于更新的是一些离散的点,比较麻烦

可以考虑这些点的共性,总是隔几个,更新一个,那窝萌把区间内的数关于k的余数分组

这样每次更新的都是其中的一组,而且是连续的。

由于 K比较小,这是本题的突破口,那么关于k的余数情况,最多只有55种。

即如果k=1,则分为1组,k=2分为2组……

一开始傻叉了打算维护55棵线段树,其实也是可以的,更新只需要1棵,查询是10棵,还是可以接受的。

不过只需要在线段树结点维护这55种情况即可。

不过内存比较紧,要把所有的情况压缩一下,不能开10*10的空间。

同样更新只需要一个,最终统计的话,需要遍历所有的K,也就是最多是10.

 


  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cmath>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include< set>
  7 #include<map>
  8 #include<queue>
  9 #include<vector>
 10 #include< string>
 11  #define Min(a,b) a<b?a:b
 12  #define Max(a,b) a>b?a:b
 13  #define CL(a,num) memset(a,num,sizeof(a));
 14  #define eps  1e-12
 15  #define inf 100000000
 16  #define mx  10
 17 
 18  const  double pi  = acos(- 1.0);
 19  const  int  maxn =  50100;
 20 typedef   __int64  ll;
 21  using  namespace std;
 22  struct node
 23 {
 24      int l;
 25      int r;
 26      int w;
 27      int add[ 55] ;
 28 }p[maxn * 4];
 29  int a[maxn], b[ 11][ 11];
 30  void build( int x, int l, int r)
 31 {
 32     p[x].l = l;
 33     p[x].r = r;
 34     CL(p[x].add, 0);
 35      if(l == r)
 36     {
 37         p[x].w = a[l];
 38          return ;
 39     }
 40      int mid = (l + r)>> 1;
 41     build( 2*x,l,mid);
 42     build( 2*x+ 1,mid+  1,r);
 43 
 44     p[x].w = p[x* 2].w + p[x* 2+ 1].w ;
 45 }
 46  void push_down( int x)
 47 {
 48      if(p[x].w)
 49     {
 50         p[x* 2].w +=p[x].w;
 51         p[x* 2+ 1].w +=p[x].w;
 52         p[x].w =  0;
 53          for( int i = 0  ; i <  55;i++)
 54         {
 55             p[x* 2].add[i] +=p[x].add[i];
 56             p[x* 2+ 1].add[i]+=p[x].add[i];
 57             p[x].add[i] =  0;
 58         }
 59     }
 60 }
 61  void update( int x, int l, int r, int num, int i, int j)
 62 {
 63      if(p[x].l == l &&p[x].r == r)
 64     {
 65         p[x].w +=num;
 66         p[x].add[b[i][j]]+=num ;
 67          return ;
 68     }
 69     push_down(x);
 70      int mid = (p[x].l + p[x].r)>> 1 ;
 71      if(l > mid)update(x* 2+ 1,l,r,num,i,j);
 72      else
 73     {
 74          if(r<=mid)update(x* 2,l,r,num,i,j);
 75          else
 76         {
 77             update(x* 2,l,mid,num,i,j);
 78             update(x* 2+ 1,mid+ 1,r,num,i,j);
 79         }
 80     }
 81 }
 82  int qury( int x, int pos)
 83 {
 84      if(p[x].l == pos&&p[x].r == pos)
 85     {
 86          int tmp =  0;
 87          for( int i =  1 ; i <=  10 ;i++)
 88         {
 89             tmp+=p[x].add[b[i][pos%i]];
 90         }
 91          return tmp + a[pos] ;
 92     }
 93     push_down(x) ;
 94      int mid = (p[x].l + p[x].r)>>  1;
 95      if(pos <= mid)   return   qury( 2*x,pos);
 96      else
 97     {
 98          return qury(x* 2+ 1,pos);
 99     }
100 }
101  int main()
102 {
103     freopen( " data.txt ", " r ",stdin);
104      int  n,s,e,k,c,i,j,q,ty;
105      int cnt =  0;
106      for(i =  1; i<=  10;i++)
107     {
108          for(j =  0;j< i;j++)
109           b[i][j] = cnt++; // 由于 内存 卡的紧 ,所以 这样编号 ,不能开 10*10 的
110      }
111      while(scanf( " %d ",&n)!=EOF)
112     {
113          for(i = 1  ; i <=n;i++)
114         {
115             scanf( " %d ",&a[i]) ;
116         }
117         build( 1, 1,n);
118         scanf( " %d ",&q);
119          while(q--)
120         {
121             scanf( " %d ",&ty);
122              if(ty== 1)
123             {
124                 scanf( " %d%d%d%d ",&s,&e,&k,&c);
125                 update( 1,s,e,c,k,s%k); //这里为什么是 s% k 呢 ,因为 : (i- s)%k = (i%k - s%k + k)%k = 0 的话 ,i%k 应该  = s%k ;
126             }
127              else
128             {
129                  int  pos;
130                 scanf( " %d ",&pos);
131                   int ans = qury( 1,pos);
132                  printf( " %d\n ",ans);
133             }
134 
135         }
136     }
137 }

 

你可能感兴趣的:(Integer)