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 }

 

posted @ 2012-09-10 22:08  Szz  阅读(667)  评论(0编辑  收藏  举报