Codeforces 920F. SUM and REPLACE / bzoj 3211 花神游历各国

题目大意:

一个数列 支持两种操作

1 把区间内的数变成他们自己的约数个数

2 求区间和

思路:

可以想到每个数最终都会变成2或1

然后我们可以线段树

修改的时候记录一下每段有没有全被修改成1或2 是的话就不修改了

不是就暴力修改 因为每个数被修改的次数很小

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstdlib>
 5 #include<cstring>
 6 #include<algorithm>
 7 #include<vector>
 8 #include<queue>
 9 #define inf 2139062143
10 #define ll long long
11 #define MAXN 1001000
12 using namespace std;
13 inline int read()
14 {
15     int x=0,f=1;char ch=getchar();
16     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
17     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
18     return x*f;
19 }
20 int n,g[MAXN],cnt[MAXN],m;
21 struct data{ll sum,mx;}tr[MAXN<<2];
22 inline void pshp(int k)
23 {
24     tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum;
25     tr[k].mx=max(tr[k<<1].mx,tr[k<<1|1].mx);
26 }
27 void build(int k,int l,int r)
28 {
29     if(l==r) {tr[k].sum=tr[k].mx=g[l];return ;}
30     int mid=(l+r)>>1;
31     build(k<<1,l,mid);build(k<<1|1,mid+1,r);
32     pshp(k);
33 }
34 inline ll query(int k,int a,int b,int l,int r)
35 {
36     if(l==a&&r==b) return tr[k].sum;
37     int mid=(l+r)>>1;
38     if(mid>=b) return query(k<<1,a,b,l,mid);
39     else if(mid<a) return query(k<<1|1,a,b,mid+1,r);
40     else return query(k<<1,a,mid,l,mid)+query(k<<1|1,mid+1,b,mid+1,r);
41 }
42 inline void upd(int k,int a,int b,int l,int r)
43 {
44     if(tr[k].mx<=2) return ;
45     if(l==r) {tr[k].sum=tr[k].mx=cnt[tr[k].mx];return ;}
46     int mid=(l+r)>>1;
47     if(mid>=b) upd(k<<1,a,b,l,mid);
48     else if(mid<a) upd(k<<1|1,a,b,mid+1,r);
49     else {upd(k<<1,a,mid,l,mid);upd(k<<1|1,mid+1,b,mid+1,r);}
50     pshp(k);
51 }
52 int main()
53 {
54     int a,b,c;
55     for(int i=1;i<=MAXN;i++)
56         for(int j=i;j<=MAXN;j+=i) cnt[j]++;
57     n=read(),m=read();
58     for(int i=1;i<=n;i++) g[i]=read();
59     build(1,1,n);
60     while(m--)
61     {
62         a=read(),b=read(),c=read();
63         if(a==1) upd(1,b,c,1,n);
64         else printf("%I64d\n",query(1,b,c,1,n));
65     }
66 }
View Code

 UPD:

bzoj 3211 区间开根号 思路同上

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstdlib>
 5 #include<cstring>
 6 #include<algorithm>
 7 #include<vector>
 8 #include<queue>
 9 #define inf 2139062143
10 #define ll long long
11 #define MAXN 100100
12 using namespace std;
13 inline int read()
14 {
15     int x=0,f=1;char ch=getchar();
16     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
17     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
18     return x*f;
19 }
20 int n,g[MAXN],m;
21 struct data{ll sum,mx;}tr[MAXN<<2];
22 inline void pshp(int k)
23 {
24     tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum;
25     tr[k].mx=max(tr[k<<1].mx,tr[k<<1|1].mx);
26 }
27 void build(int k,int l,int r)
28 {
29     if(l==r) {tr[k].sum=tr[k].mx=g[l];return ;}
30     int mid=(l+r)>>1;
31     build(k<<1,l,mid);build(k<<1|1,mid+1,r);
32     pshp(k);
33 }
34 inline ll query(int k,int a,int b,int l,int r)
35 {
36     if(l==a&&r==b) return tr[k].sum;
37     int mid=(l+r)>>1;
38     if(mid>=b) return query(k<<1,a,b,l,mid);
39     else if(mid<a) return query(k<<1|1,a,b,mid+1,r);
40     else return query(k<<1,a,mid,l,mid)+query(k<<1|1,mid+1,b,mid+1,r);
41 }
42 inline void upd(int k,int a,int b,int l,int r)
43 {
44     if(tr[k].mx<=1) return ;
45     if(l==r) {tr[k].sum=tr[k].mx=sqrt(tr[k].sum);return ;}
46     int mid=(l+r)>>1;
47     if(mid>=b) upd(k<<1,a,b,l,mid);
48     else if(mid<a) upd(k<<1|1,a,b,mid+1,r);
49     else {upd(k<<1,a,mid,l,mid);upd(k<<1|1,mid+1,b,mid+1,r);}
50     pshp(k);
51 }
52 int main()
53 {
54     int a,b,c;
55     n=read();
56     for(int i=1;i<=n;i++) g[i]=read();
57     m=read();
58     build(1,1,n);
59     while(m--)
60     {
61         a=read(),b=read(),c=read();
62         if(a==2) upd(1,b,c,1,n);
63         else printf("%lld\n",query(1,b,c,1,n));
64     }
65 }
View Code
posted @ 2018-02-14 16:49  jack_yyc  阅读(287)  评论(0编辑  收藏  举报