首页 > 其他 > 详细

[HDU 5634] Rikka with Phi

时间:2020-03-04 15:38:31      阅读:62      评论:0      收藏:0      [点我收藏+]

维护一个数据结构,支持区间覆盖,区间取phi,区间查询和。
区间取phi,理论分析,对于一个偶数取phi变为原来的一半,奇数取phi变为偶数。所以最多log次,就可以将一个数变成1。而phi(1)=1,所以可以通过维护区间最大值,若一段区间最大值已经是1,那么就不必修改了,这个时候时间复杂度为\(O(\log^2n)\)
而两个操作结合起来,就有点麻烦,因为覆盖之后不好取phi,所以需要引入一个标记,记录一个区间所有值是否相等,这样的话一次覆盖最多遍历log个区间,修改复杂度也得到了保证。

#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<vector>
#include<set>
#include<map>
#include<string>
#include<iostream>
#include<queue>
#include<cctype>
using namespace std;

#define A(x) cout << #x << " " << x << endl;
#define AA(x,y) cout << #x << " " << x << #y << " " << y << endl;
#define B cout << "Break" << endl;
#define ll long long
#define inf 1000000000

int read()
{
    int c = getchar();
    int x = 0,f = 1;
    while(!isdigit(c))
    {
        if(c == '-') f = -1;
        c = getchar();
    }
    while(isdigit(c))
    {
        x = x * 10 + c - '0';
        c = getchar();
    }
    return f * x;
}
#define N 300010
int sum[N << 2],lazy[N << 2],mx[N << 2],tag[N << 2],seq[N];
#define MAX 10000010
int pr[MAX],pn,phi[MAX],vis[MAX];
int n,m;
void sieve()
{
    phi[1] = 1;
    for(int i = 2;i <= MAX - 10;++i)
    {
        if(!vis[i])
        {
            phi[i] = i - 1;
            pr[++pn] = i;
        }
        for(int j = 1;j <= pn && i * pr[j] <= MAX - 10;++i)
        {
            vis[i * pr[j]] = 1;
            if(i % pr[j] == 0)
            {
                phi[i * pr[j]] = phi[i] * pr[j];
                break;
            }
            phi[i * pr[j]] = phi[i] * phi[pr[j]];
        }
    }
}
#define mid (l + r >> 1)
#define ls x << 1,l,mid
#define rs x << 1 | 1,mid + 1,r
void push_up(int x)
{
    sum[x] = sum[x << 1] + sum[x << 1 | 1];
    mx[x] = max(mx[x << 1],mx[x << 1 | 1]);
    tag[x] = (tag[x << 1] && tag[x << 1 | 1] && mx[x << 1] == mx[x << 1 | 1]);
    return;
}
void build(int x,int l,int r)
{
    sum[x] = mx[x] = tag[x] = lazy[x] = 0;
    if(l == r)
    {
        sum[x] = mx[x] = seq[l];
        tag[x] = 1;
        return;
    }
    build(ls);
    build(rs);
    push_up(x);
}
void add(int x,int l,int r,int k)
{
    lazy[x] = mx[x] = k;
    tag[x] = 1;
    sum[x] = (r - l + 1) * k;
    return;
}
void push_down(int x,int l,int r)
{
    if(!lazy[x]) return;
    add(ls,lazy[x]);
    add(rs,lazy[x]);
    lazy[x] = 0;
    return;
}
void to_phi(int x,int l,int r,int p,int q)
{
    if(mx[x] <= 1) return;
    if(p <= l && r <= q && tag[x])
    {
        lazy[x] = mx[x] = phi[mx[x]];
        sum[x] = (r - l + 1) * mx[x];
        return;
    }
    push_down(x,l,r);
    if(p <= mid) to_phi(ls,p,q);
    if(q > mid) to_phi(rs,p,q);
    push_up(x);
    return;
}
void modify(int x,int l,int r,int p,int q,int k)
{
    if(p <= l && r <= q)
    {
        tag[x] = 1;
        lazy[x] = mx[x] = k;
        sum[x] = (r - l + 1) * k;
        return;
    }
    push_down(x,l,r);
    if(p <= mid) modify(ls,p,q,k);
    if(q > mid) modify(rs,p,q,k);
    push_up(x);
    return;
}
int query(int x,int l,int r,int p,int q)
{
    if(p <= l && r <= q) return sum[x];
    int ret = 0;
    push_down(x,l,r);
    if(p <= mid) ret += query(ls,p,q);
    if(q > mid) ret += query(rs,p,q);
    return ret;
}
int main()
{
    sieve();
    int T = read();
    while(T--)
    {
        int n = read(),m = read();
        for(int i = 1;i <= n;++i) seq[i] = read();
        build(1,1,n);
        while(m--)
        {
            int op = read(),l = read(),r = read();
            if(op == 1) to_phi(1,1,n,l,r);
            if(op == 2)
            {
                int k = read();
                modify(1,1,n,l,r,k);
            }
            if(op == 3) printf("%d\n",query(1,1,n,l,r));
        }

    }
}

[HDU 5634] Rikka with Phi

原文:https://www.cnblogs.com/lijilai-oi/p/12409521.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!