HDU 5634 线段树

Posted scaulok

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 5634 线段树相关的知识,希望对你有一定的参考价值。

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

题意:给出 n 个数,有三种操作,把区间的 ai 变为 φ(ai);把区间的 ai 变为 x;查询区间和。

题解:因为一个数由 ai 变为 φ(ai)在 log 次之后会变为 1 并且一直都为 1,考虑在没有第二种操作的情况下,只需要暴力修改记录区间最大值是否大于 1 即可。在加入第二个操作之后,可以发现对区间进行修改的话,一个区间内的数都是相同的,进行第一个操作可以对整个区间进行操作,故可以用线段树多记录一个区间内的数是否相同即可。

 

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 #define ll long long
  4 #define ull unsigned long long
  5 #define mst(a,b) memset((a),(b),sizeof(a))
  6 #define mp(a,b) make_pair(a,b)
  7 #define pi acos(-1)
  8 #define pii pair<int,int>
  9 #define pb push_back
 10 const int INF = 0x3f3f3f3f;
 11 const double eps = 1e-6;
 12 const int MAXN = 3e5 + 10;
 13 const int MAXM = 1e7 + 10;
 14 const ll mod = 1e9 + 7;
 15 
 16 bool check[MAXM];
 17 int phi[MAXM], prime[MAXM / 10], tot;
 18 
 19 void init(int N) {
 20     tot = 0;
 21     phi[1] = 1;
 22     for(int i = 2; i <= N; i++) {
 23         if(!check[i]) {
 24             prime[tot++] = i;
 25             phi[i] = i - 1;
 26         }
 27         for(int j = 0; j < tot; j++) {
 28             if(i * prime[j] > N) break;
 29             check[i * prime[j]] = true;
 30             if(i % prime[j] == 0) {
 31                 phi[i * prime[j]] = phi[i] * prime[j];
 32                 break;
 33             } else phi[i * prime[j]] = phi[i] * (prime[j] - 1);
 34         }
 35     }
 36 }
 37 
 38 int a[MAXN],num[MAXN<<2];
 39 ll sum[MAXN<<2];
 40 
 41 void pushup(int rt) {
 42     sum[rt] = sum[rt<<1] + sum[rt<<1|1];
 43     if(num[rt<<1] == num[rt<<1|1]) num[rt] = num[rt<<1];
 44     else num[rt] = 0;
 45 //    num[rt] = (num[rt<<1] == num[rt<<1|1]) ? num[rt] : 0;
 46 }
 47 
 48 void build(int rt,int l,int r) {
 49     if(l == r) {
 50         sum[rt] = num[rt] = a[l];
 51         return ;
 52     }
 53     int mid = (l + r) >> 1;
 54     build(rt<<1,l,mid);
 55     build(rt<<1|1,mid + 1,r);
 56     pushup(rt);
 57 }
 58 
 59 void pushdown(int rt,int l,int r) {
 60     if(num[rt]) {
 61         int mid = (l + r) >> 1;
 62         num[rt<<1] = num[rt<<1|1] = num[rt];
 63         sum[rt<<1] = 1ll * num[rt<<1] * (mid - l + 1);
 64         sum[rt<<1|1] = 1ll * num[rt<<1|1] * (r - mid);
 65         num[rt] = 0;
 66     }
 67 }
 68 
 69 void update1(int rt,int l,int r,int ql,int qr) {
 70     if(ql > qr) return ;
 71     if(num[rt] && l == ql && r == qr) {
 72         num[rt] = phi[num[rt]];
 73         sum[rt] = 1ll * num[rt] * (r - l + 1);
 74         return ;
 75     }
 76     pushdown(rt,l,r);
 77     int mid = (l + r) >> 1;
 78     if(qr <= mid) update1(rt<<1,l,mid,ql,qr);
 79     else if(ql > mid) update1(rt<<1|1,mid + 1,r,ql,qr);
 80     else {
 81         update1(rt<<1,l,mid,ql,mid);
 82         update1(rt<<1|1,mid + 1,r,mid + 1,qr);
 83     }
 84     pushup(rt);
 85 }
 86 
 87 void update2(int rt,int l,int r,int ql,int qr,int val) {
 88     if(ql > qr) return ;
 89     if(l == ql && r == qr) {
 90         num[rt] = val;
 91         sum[rt] = 1ll * num[rt] * (r - l + 1);
 92         return ;
 93     }
 94     pushdown(rt,l,r);
 95     int mid = (l + r) >> 1;
 96     if(qr <= mid) update2(rt<<1,l,mid,ql,qr,val);
 97     else if(ql > mid) update2(rt<<1|1,mid + 1,r,ql,qr,val);
 98     else {
 99         update2(rt<<1,l,mid,ql,mid,val);
100         update2(rt<<1|1,mid + 1,r,mid + 1,qr,val);
101     }
102     pushup(rt);
103 }
104 
105 ll query(int rt,int l,int r,int ql,int qr) {
106     if(ql == l && qr == r) return sum[rt];
107     pushdown(rt,l,r);
108     int mid = (l + r) >> 1;
109     if(qr <= mid) return query(rt<<1,l,mid,ql,qr);
110     else if(ql > mid) return query(rt<<1|1,mid + 1,r,ql,qr);
111     else return query(rt<<1,l,mid,ql,mid) + query(rt<<1|1,mid + 1,r,mid + 1,qr);
112 }
113 
114 int main() {
115 #ifdef local
116     freopen("data.txt", "r", stdin);
117 //    freopen("data.txt", "w", stdout);
118 #endif
119     init(1e7);
120     int t;
121     scanf("%d",&t);
122     while(t--) {
123         int n,m;
124         scanf("%d%d",&n,&m);
125         for(int i = 1; i <= n; i++) scanf("%d",&a[i]);
126         build(1,1,n);
127         while(m--) {
128             int op,l,r,x;
129             scanf("%d",&op);
130             if(op == 1) {
131                 scanf("%d%d",&l,&r);
132                 update1(1,1,n,l,r);
133             } else if(op == 2) {
134                 scanf("%d%d%d",&l,&r,&x);
135                 update2(1,1,n,l,r,x);
136             } else if(op == 3) {
137                 scanf("%d%d",&l,&r);
138                 printf("%lld
",query(1,1,n,l,r));
139             }
140         }
141     }
142     return 0;
143 }

 

以上是关于HDU 5634 线段树的主要内容,如果未能解决你的问题,请参考以下文章

HDU 5634 Rikka with Phi

HDU 5634 Rikka with Phi

hdu-1540线段树刷题

HDU 5692 线段树

hdu6464 线段树

HDU 3016 Man Down(线段树)