ZOJ 3911 线段树

题意:有N个数字,M个操作,然后回答每个Q开头的询问

操作形式:

A val pos:在pos位置上+val

Q l r:询问l~r之间有多少个质数

R val l r:把l~r之间的数字替换成val

分析:建成两棵树,一棵更新 原数列,一棵更新 质数序列(只有0,1)

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cmath>
  4 #include <algorithm>
  5 using namespace std;
  6 #define repu(i,a,b) for(int i=a;i<b;i++)
  7 #define lson l , m , rt << 1
  8 #define rson m + 1 , r , rt << 1 | 1
  9 const int maxn = 111111;
 10 const int M = 10000010;
 11 int h , w , n;
 12 bool p[M];
 13 int prime()
 14 {
 15     memset(p,false,sizeof(p));
 16     p[0] = p[1] = true;
 17     for(int i = 4; i <= M; i += 2)
 18         p[i] = true;
 19     for(int i = 3; i <= sqrt(M); i+=2)
 20     {
 21         int k = i * 2;
 22         for(int j = i*i; j <= M; j += k)
 23             p[j] = true;
 24     }
 25 }
 26 struct Segment
 27 {
 28     int col[maxn<<2];
 29     int sum[maxn<<2];
 30     void init()
 31     {
 32         memset(col,0,sizeof(col));
 33         memset(sum,0,sizeof(sum));
 34     }
 35     void PushUp(int rt)
 36     {
 37         sum[rt] = sum[rt<<1] + sum[rt<<1|1];
 38     }
 39     void PushDown(int rt,int m)
 40     {
 41         if(col[rt] != -1)///如果是0就进不去
 42         {
 43             col[rt<<1] = col[rt<<1|1] = col[rt];
 44             sum[rt<<1] = (m - (m >> 1)) * col[rt];
 45             sum[rt<<1|1] = (m >> 1) * col[rt];
 46             col[rt] = -1;
 47         }
 48     }
 49     void build(int l,int r,int rt)
 50     {
 51         col[rt] = -1;
 52         sum[rt] = 0;
 53         if (l == r) return ;
 54         int m = (l + r) >> 1;
 55         build(lson);
 56         build(rson);
 57         PushUp(rt);
 58     }
 59     void Update(int p,int add,int l,int r,int rt)
 60     {
 61         if(l == r)
 62         {
 63             sum[rt] += add;
 64             return ;
 65         }
 66         PushDown(rt , r - l + 1);
 67         int m = (l + r) >> 1;
 68         if (p <= m) Update(p, add, lson);
 69         else Update(p, add, rson);
 70         PushUp(rt);
 71     }
 72     void update(int L,int R,int c,int l,int r,int rt)
 73     {
 74         if (L <= l && r <= R)
 75         {
 76             col[rt] = c;
 77             ///因为序列只有0,1;如果初始化为0的话,赋值有可能赋成0,pushdown就进不了,也就跟新不了数据了
 78             sum[rt] = c * (r - l + 1);
 79             return ;
 80         }
 81         PushDown(rt , r - l + 1);
 82         int m = (l + r) >> 1;
 83         if (L <= m) update(L , R , c , lson);
 84         if (R > m) update(L , R , c , rson);
 85         PushUp(rt);
 86     }
 87     int query(int L,int R,int l,int r,int rt)
 88     {
 89         if (L <= l && r <= R)
 90         {
 91             return sum[rt];
 92         }
 93         PushDown(rt , r - l + 1);
 94         int m = (l + r) >> 1;
 95         int ret = 0;
 96         if (L <= m) ret += query(L , R , lson);
 97         if (m < R) ret += query(L , R , rson);
 98         PushUp(rt);
 99         return ret;
100     }
101 } Seg,seg;
102 int main()
103 {
104     int T , n , m, a , b , c;
105     prime();
106     scanf("%d",&T);
107     for (int cas = 1 ; cas <= T ; cas ++)
108     {
109         Seg.init();
110         seg.init();
111         scanf("%d%d",&n,&m);
112         Seg.build(1 , n , 1);
113         seg.build(1 , n , 1);
114         repu(i,1,n+1)
115         {
116             scanf("%d",&a);
117             Seg.Update(i,a,1,n,1);
118             if(!p[a])///如果是质数才加1
119                 seg.Update(i,1,1,n,1);
120         }
121         char s[4];
122         while(m--)
123         {
124             scanf("%s",s);
125             if(s[0] == 'R')
126             {
127                 scanf("%d%d%d",&a, &b, &c);
128                 Seg.update(b , c , a , 1 , n , 1);
129                 if(!p[a])///如果是质数,更新成1
130                     seg.update(b , c , 1 , 1 , n , 1);
131                 else
132                     seg.update(b , c , 0 , 1 , n , 1);
133             }
134             else if(s[0] == 'A')
135             {
136                 scanf("%d%d",&a,&b);///在b位置上加a,如果加的数字成了质数,也得更新另一棵树
137                 int t = Seg.query(b,b,1,n,1);
138                 Seg.Update(b,a,1,n,1);
139                 if(!p[t+a] && p[t])///原本不是质数,变成了质数
140                     seg.Update(b,1,1,n,1);
141                 else if(p[t+a] && !p[t])///原本是质数,变成了合数
142                     seg.Update(b,-1,1,n,1);
143                 else if(p[t+a] && p[t]) ;
144                 else if(!p[t+a] && !p[t]) ;
145             }
146             else
147             {
148                 scanf("%d%d",&a,&b);
149                 printf("%d\n",seg.query(a,b,1,n,1));
150             }
151         }
152     }
153     return 0;
154 }
AC代码

 

posted @ 2015-10-13 18:39  一麻袋码的玛侬  阅读(327)  评论(0编辑  收藏  举报