HDU 5634 Rikka with Phi(线段树)

来源:互联网 发布:淘宝违规申诉成功率 编辑:程序博客网 时间:2024/06/10 03:10

题目链接:点击打开链接

题意:有3种区间操作, 1是把区间内的所有数变成它的欧拉函数值, 2是把区间所有数都变成一个数x,3是查询区间和。

思路:后两个操作就是线段树的区间修改和求和, 没什么好说的。 

题解说用平衡树(弱不会), 不过大致思路线段树同样可以维护, 因为一个数进行最多phiO(logn)次就会变成1, 所以我们可以在递归结束,向上传标记的时候顺便看看其子区间是不是都等于1, 是就合并起来, 给这个点重新标记。 

细节参见代码:

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<string>#include<vector>#include<stack>#include<bitset>#include<cstdlib>#include<cmath>#include<set>#include<list>#include<deque>#include<map>#include<queue>using namespace std;typedef long long ll;typedef long double ld;const ld EPS = 1e-9, PI = 3.1415926535897932384626433832795;const int mod = 1000000000 + 7;const int INF = int(1e9);const ll INF64 = ll(1e18);const int maxn = 300000 + 10;int T, n, m, v, id, l, r, x;ll sum[maxn<<2], setv[maxn<<2];#define Max 10000010ll euler[Max] = {0};void Init(){     euler[1]=1;     for(ll i=2;i<Max;i++)       euler[i]=i;     for(ll i=2;i<Max;i++)        if(euler[i]==i)           for(ll j=i;j<Max;j+=i)              euler[j]=euler[j]/i*(i-1);}void PushUp(int o) {    sum[o] = sum[o<<1] + sum[o<<1|1];    if(setv[o<<1] == setv[o<<1|1]) setv[o] = setv[o<<1];    else setv[o] = 0;}void build(int l, int r, int o) {    int m = (l + r) >> 1;    sum[o] = 0;    setv[o] = 0;    if(l == r) {        scanf("%d",&v);        sum[o] = setv[o] = v;        return ;    }    build(l, m, o<<1);    build(m+1, r, o<<1|1);    PushUp(o);}void pushdown(int l, int r, int o) {    if(setv[o]) {        int m = (l + r) >> 1;        setv[o<<1] = setv[o<<1|1] = setv[o];        sum[o<<1] = (ll)(m - l + 1) * setv[o];        sum[o<<1|1] = (ll)(r - m) * setv[o];        setv[o] = 0;    }}void update(int L, int R, int v, int l, int r, int o) {    int m = (l + r) >> 1;    if(L <= l && r <= R) {        setv[o] = (ll)v;        sum[o] = (ll)v * (r - l + 1);        return ;    }    pushdown(l, r, o);    if(L <= m) update(L, R, v, l, m, o<<1);    if(m < R) update(L, R, v, m+1, r, o<<1|1);    PushUp(o);}void haha(int L, int R, int l, int r, int o) {    int m = (l + r) >> 1;    if(setv[o] && L <= l && r <= R) {        setv[o] = euler[setv[o]];        sum[o] = setv[o] * (r - l + 1);        return ;    }    if(l == r) return ;    pushdown(l, r, o);    if(L <= m) haha(L, R, l, m, o<<1);    if(m < R) haha(L, R, m+1, r, o<<1|1);    PushUp(o);}ll query(int L, int R, int l, int r, int o) {    int m = (l + r) >> 1;    if(L <= l && r <= R) {        return sum[o];    }    pushdown(l, r, o);    ll ans = 0;    if(L <= m) ans += query(L, R, l, m, o<<1);    if(m < R) ans += query(L, R, m+1, r, o<<1|1);    PushUp(o);    return ans;}int main() {    Init();    scanf("%d",&T);    while(T--) {        scanf("%d%d",&n,&m);        build(1, n, 1);        while(m--) {            scanf("%d%d%d",&id,&l,&r);            if(id == 1) haha(l, r, 1, n, 1);            else if(id == 2) {                scanf("%d",&x);                update(l, r, x, 1, n, 1);            }            else printf("%I64d\n",query(l, r, 1, n, 1));        }    }    return 0;}


0 0
原创粉丝点击