1. 程式人生 > >Educational Codeforces Round 37 (Rated for Div. 2)F. SUM and REPLACE+線段樹

Educational Codeforces Round 37 (Rated for Div. 2)F. SUM and REPLACE+線段樹

namespace ted amp return Education span num sign define

題目鏈接:F. SUM and REPLACE

題意:給一個數組,兩種操作,第一種把[L,R]的數變成這個數的因子個數(這個是log級別的下降),第二種求[L,R]的和

題解:我們發現當數字到1或2後就不會更改,我們用兩個線段樹,一個維護和,一個維護區間最大值,當區間的最大值小於等於2的時候就可以不用更新了。

#include<bits/stdc++.h>
#include<set>
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#define
pb push_back #define ll long long #define PI 3.14159265 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define eps 1e-7 typedef unsigned long long ull; const int mod=1e9+7; const int maxn=3e5+5; const int root=1e6+7; using namespace std; int a[maxn],ma[maxn<<2],n,q,num[root]; ll tree[maxn
<<2]; void push(int rt) { ma[rt]=max(ma[rt<<1],ma[rt<<1|1]); tree[rt]=tree[rt<<1]+tree[rt<<1|1]; return ; } void init() { for(int i=0;i<root;i++)num[i]=1; for(int i=2;i<root;i++) { for(int j=i;j<root;j+=i) { num[j]
++; } } } void built(int l,int r,int rt) { if(l==r) { tree[rt]=ma[rt]=a[l]; return ; } int m=(l+r)/2; built(ls); built(rs); push(rt); } void update(int L,int R,int l,int r,int rt) { //if(r<L||l>R)return ; if(l==r) { ma[rt]=num[ma[rt]]; tree[rt]=num[tree[rt]];return ; } int m=(l+r)/2; if(L<=m&&ma[rt<<1]>2) update(L,R,ls); if(R>m&&ma[rt<<1|1]>2) update(L,R,rs); push(rt); } ll query(int L,int R,int l,int r,int rt) { //if(r<L||l>R)return 0; if(L<=l&&r<=R) { return tree[rt]; } ll ans=0; int m=(l+r)/2; if(L<=m) ans+=query(L,R,ls); if(R>m) ans+=query(L,R,rs); return ans; } int main() { init(); scanf("%d %d",&n,&q); for(int i=1;i<=n;i++)scanf("%d",&a[i]); built(1,n,1); while(q--) { int op,x,y; scanf("%d %d %d",&op,&x,&y); if(op==1) { update(x,y,1,n,1); } else { printf("%lld\n",query(x,y,1,n,1)); } } return 0; }

Educational Codeforces Round 37 (Rated for Div. 2)F. SUM and REPLACE+線段樹