【hdu4267 A Simple Problem with Integers】 线段树之区间操作

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4267

 

题目大意:给你一列数区间范围为[1,n],区间每个数有一个对应值a[i]。接下来有Q个操作

操作1: "1 a b k c", 区间[a,b]内满足条件(i-a)%k==0的数值a[i]加c。

操作2:“2 a” ,输出a[i]的值。

 

解题思路:这题蛋都碎成渣渣了,RE几次,MLE无数次。

1、按线段树建树情况可推出,即使成为完全平衡树开也只有2*n-1个节点,开2*n的大小完全没问题啊,但它就是RE,不解。

2、这题我的初始化开始没有建build()函数,而是直接对flag[][]初始化,这里MLE无数次,建树开build()函数成段成段初始化就过了,蛋都碎成渣渣了。

 

说说解题思路吧,重点在(i-a)%k==0,这样的i是断开的,无法成段操作,傻×才去暴力。注意到k比较小,枚举k以及余数的组合,k=1有1种,k=2有2种,……k=10有10种,所以总共有(1+2+3....+10=55种组合),我们将每种组合压缩成一个状态。

建树操作: 成段初始化,不然MLE。

更新操作: 当查询到对应区间[tl,tr],对应的组合状态flag[u][mo]加上c,返回。

查询操作:对x路过的区间进行操作,当x与k(1<=k<=10)对应的余数值这个状态有值时,加上这个值。

 

View Code
 1 #include <iostream>

 2 #include <cstdio>

 3 #include <cstring>

 4 #include <vector>

 5 using namespace std;

 6 

 7 #define lz 2*u,l,mid

 8 #define rz 2*u+1,mid+1,r

 9 const int maxn=500005;

10 int flag[4*maxn][55], val[maxn];

11 

12 void build(int u, int l, int r)  ///开始没这样建树初始化,而是直接memset(flag,0,sizeof(flag)),一直MLE,蛋都碎成渣渣了

13 {

14     memset(flag[u],0,sizeof(flag[u]));

15     if(l==r) return ;

16     int mid=(l+r)>>1;

17     build(lz);

18     build(rz);

19 }

20 

21 void Update(int u, int l, int r, int tl, int tr, int mo, int k, int c)

22 {

23     if(tl<=l&&r<=tr)

24     {

25         for(int i=1; i<k; i++) mo+=i;

26         flag[u][mo]+=c;

27         return ;

28     }

29     int mid=(l+r)>>1;

30     if(tr<=mid) Update(lz,tl,tr,mo,k,c);

31     else if(tl>mid) Update(rz,tl,tr,mo,k,c);

32     else

33     {

34         Update(lz,tl,mid,mo,k,c);

35         Update(rz,mid+1,tr,mo,k,c);

36     }

37 }

38 

39 void Query(int u, int l, int r, int x, int &res)

40 {

41     for(int i=1; i<=10; i++)

42     {

43         int mo=x%i;

44         for(int j=1; j<i; j++) mo+=j;

45         res+=flag[u][mo];

46     }

47     if(l==r) return ;

48     int mid=(l+r)>>1;

49     if(x<=mid) Query(lz,x,res);

50     else Query(rz,x,res);

51 }

52 

53 int main()

54 {

55     int n, Q;

56     while(~scanf("%d",&n))

57     {

58         for(int i=1; i<=n; i++) scanf("%d",val+i);

59         int op, a, b, k, c;

60         build(1,1,n);

61         scanf("%d",&Q);

62         while(Q--)

63         {

64             scanf("%d",&op);

65             if(op==1)

66             {

67                 scanf("%d%d%d%d",&a,&b,&k,&c);

68                 Update(1,1,n,a,b,a%k,k,c);

69             }

70             else

71             {

72                 scanf("%d",&a);

73                 int res=0;

74                 Query(1,1,n,a,res);

75                 printf("%d\n",res+val[a]);

76             }

77         }

78     }

79     return 0;

80 }

 

你可能感兴趣的:(Integer)