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 }
人生就像心电图,想要一帆风顺,除非game-over