Rikka with Phi
Accepts: 5
Submissions: 66
Time Limit: 16000/8000 MS (Java/Others)
Memory Limit: 131072/131072 K (Java/Others)
/* BestCoder Round #73 (div.1) hdu5634 Rikka with Phi 本来最开始用伸展树(主要是线段树不是很熟)的,但是中间有点问题,导致一直是TLE,于是乎 就去写线段树了 感觉对线段树的理解上有很多问题TAT 思路:先打个表然后用线段树(平衡树)去解决 主要是有same标记,sum和,欧拉 中间在将一个区间改变成欧拉时,如果中间遇到了区间的same,直接 修改这个标记就好的 hhh-2016-02-25 17:54:59 */ #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <cmath> #include <stack> using namespace std; typedef long long ll; typedef long double ld; const int maxn = 300010; ll euler[10000010] = {0}; void getEuler() { euler[1] = 1; for(ll i =2 ; i <= 10000000; i++) { if(!euler[i]) { for(ll j = i; j <= 10000000; j += i) { if(!euler[j]) euler[j] = j; euler[j] = euler[j]/i*(i-1); } } } } struct node { int l,r; ll sum,same; } segtree[maxn<<2]; void push_up(int r) { int lson = r<<1,rson = (r<<1)|1; segtree[r].sum = segtree[lson].sum + segtree[rson].sum; if(segtree[lson].same == segtree[rson].same) segtree[r].same = segtree[lson].same; else segtree[r].same = 0; } void build(int i ,int l,int r) { segtree[i].l = l,segtree[i].r = r; segtree[i].sum = segtree[i].same = 0; if(l == r) { scanf("%I64d",&segtree[i].same); segtree[i].sum = segtree[i].same; return ; } int mid = (l+r)>>1; build(i<<1,l,mid); build((i<<1)|1,mid+1,r); push_up(i); } void push_down(int r) { int lson = r<<1,rson = (r<<1)|1; if(segtree[r].same) { segtree[lson].same = segtree[r].same; segtree[rson].same = segtree[r].same; segtree[lson].sum = (ll)(segtree[lson].r - segtree[lson].l+1)*segtree[r].same; segtree[rson].sum = (ll)(segtree[rson].r - segtree[rson].l+1)*segtree[r].same; segtree[r].same = 0; } } void make_euler(int i,int l,int r) { //区间修改 if(segtree[i].r <= r && segtree[i].l >= l && segtree[i].same) { segtree[i].same = (ll)euler[segtree[i].same]; segtree[i].sum = segtree[i].same*(ll)(segtree[i].r-segtree[i].l+1); return; } if(l == r) return ; int mid = (segtree[i].r +segtree[i].l) >>1; push_down(i); if(l <= mid) make_euler(i<<1,l,r); if(r > mid) make_euler((i<<1)|1,l,r); push_up(i); } void make_same(int i,int l,int r,ll c) { if(segtree[i].r <= r && segtree[i].l >= l) { segtree[i].same = c; segtree[i].sum = segtree[i].same*(ll)(segtree[i].r-segtree[i].l+1); return; } int mid = (segtree[i].r +segtree[i].l) >>1; push_down(i); if(l <= mid) make_same(i<<1,l,r,c); if(r > mid) make_same((i<<1)|1,l,r,c); push_up(i); } ll get_sum(int i,int l,int r) { int mid = (segtree[i].l + segtree[i].r) >> 1; if(segtree[i].l >= l && segtree[i].r <= r) { return segtree[i].sum; } push_down(i); ll ans = 0; if(l <= mid) ans += get_sum(i<<1,l,r); if(r > mid) ans += get_sum(i<<1|1,l,r); push_up(i); return ans; } int main() { int T,n,m; getEuler(); scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); build(1,1,n); for(int i =1; i <= m; i++) { int op,l,r; ll c; scanf("%d",&op); if(op == 1) { scanf("%d%d",&l,&r); make_euler(1,l,r); //debug(); } else if(op == 2) { scanf("%d%d%I64d",&l,&r,&c); make_same(1,l,r,c); // debug(); } else if(op == 3) { scanf("%d%d",&l,&r); printf("%I64d ",get_sum(1,l,r)); } } } return 0; }