zoukankan      html  css  js  c++  java
  • HDU 5634 Rikka with Phi

    题目大意:给一个序列,支持区间求 phi、区间赋值、区间求和。

    (n,mleq 3* 10^5,A_ileq10^7)

    线段树直接暴力。

    一个数在不断变成它的欧拉函数若干次之后恒为一,且许多数的欧拉函数值都是相同的。这样的话,如果我们将修改操作进行改进,只有在当前区间在询问区间以内且当前区间中的数都相同时,我们才对这个区间进行修改,否则我们继续对其的左右儿子进行修改。

    #define B cout << "BreakPoint" << endl;
    #define O(x) cout << #x << " " << x << endl;
    #define O_(x) cout << #x << " " << x << " ";
    #define Msz(x) cout << "Sizeof " << #x << " " << sizeof(x)/1024/1024 << " MB" << endl;
    #include<cstdio>
    #include<cmath>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<set>
    #define LL long long
    const int inf = 1e9 + 9;
    const int N = 3e5 + 5;
    const int M = 10000000 + 5;
    using namespace std;
    inline int read() {
    	int s = 0,w = 1;
    	char ch = getchar();
    	while(ch < '0' || ch > '9') {
    		if(ch == '-')
    			w = -1;
    		ch = getchar();
    	}
    	while(ch >= '0' && ch <= '9') {
    		s = s * 10 + ch - '0';
    		ch = getchar();
    	}
    	return s * w;
    }
    using namespace std;
    LL phi[M],pn[M];
    bool vis[M];
    int n,m,a[N],tot;
    void init(){
        phi[1] = 1;
        for(int i = 2;i <= M - 5;i++){
            if(!vis[i]) pn[++tot] = i,phi[i] = i - 1;
            for(int j = 1;j <= tot;++j){
                if(i * pn[j] > M - 5)break;
                vis[i * pn[j]] = 1;
                if(i % pn[j] == 0){
                    phi[i * pn[j]] = phi[i] * pn[j];
                    break;
                }
                phi[i * pn[j]] = phi[i] * (pn[j] - 1);
            }
        }
    }
    namespace Segment{
    	struct node{
    		int l,r;
    		LL sum,num;
    	}t[N<<2];
    	#define ls (k<<1)
    	#define rs (k<<1|1)
    	#define mid (t[k].l + t[k].r>>1)
    	void pushup(int k){
    	    t[k].sum = t[ls].sum + t[rs].sum;
    	    t[k].num = t[ls].num == t[rs].num ? t[ls].num : 0;
    	}
    	void pushnow(int k,LL v){
    	    t[k].num = v;
    	    t[k].sum = v * (t[k].r - t[k].l + 1);
    	}
    	void pushdown(int k){
    	    if(!t[k].num) return;
    	    pushnow(ls,t[k].num),pushnow(rs,t[k].num);
    	}
    	void build(int k,int l,int r){
    	    t[k].l = l,t[k].r = r;
    	    if(l == r){
    	        t[k].num = t[k].sum = a[l];
    	        return;
    	    }
    	    build(ls,l,mid);
    	    build(rs,mid + 1,r);
    	    pushup(k);
    	}
    	void modify(int k,int l,int r){
    	    if(r < t[k].l || t[k].r < l) return;
    	    if(l <= t[k].l && t[k].r <= r && t[k].num){
    	        pushnow(k,phi[t[k].num]);
    	        return;
    	    }
    	    pushdown(k);
    	    if(r <= mid) modify(ls,l,r);
    	    else if(l > mid) modify(rs,l,r);
    	    else modify(ls,l,mid),modify(rs,mid + 1,r);
    	    pushup(k);
    	}
    	void update(int k,int l,int r,LL v){
    	    if(r < t[k].l || t[k].r < l) return;
    	    if(l <= t[k].l && t[k].r <= r){
    	        pushnow(k,v);
    	        return;
    	    }
    	    pushdown(k);
    	    if(r <= mid) update(ls,l,r,v);
    	    else if(l > mid) update(rs,l,r,v);
    	    else update(ls,l,mid,v),update(rs,mid+1,r,v);
    	    pushup(k);
    	}
    	inline LL query(int k,int l,int r){
    	    if(r < t[k].l || t[k].r < l) return 0;
    	    if(l <= t[k].l && t[k].r <= r) return t[k].sum;
    	    pushdown(k);
    	    if(r <= mid) return query(ls,l,r);
    	    if(l > mid) return query(rs,l,r);
    	    return query(ls,l,mid) + query(rs,mid+1,r);
    	}
    }
    using namespace Segment;
    void pre(){
    	memset(t,0,sizeof(t));
        n = read(),m = read();
        for(int i = 1;i <= n;i++) a[i] = read();
        build(1,1,n);
        return ;
    }
    void solve(){
    	int op = read(),l = read(),r = read();
        if(op == 1) modify(1,l,r);
        if(op == 2){
            LL v = read();
            update(1,l,r,v);
        }
        if(op == 3) printf("%lld
    ",query(1,l,r));
        return ;
    }
    int main(){
        init();
        int T = read();
        while(T--){
            pre();
            while(m--) solve();
        }
        return 0;
    }
    
  • 相关阅读:
    cocos2d中sprite动画接口及动画实现思路总结
    iOS开发:小技巧积累
    cocos2d使用定时器
    Eclipse报错:cannot connect to VM
    Myeclipse console 端没有 tomcat 启动的log信息
    MyEclipse Web项目不能自动编译
    在MyEclipse中如何查看Spring/Hibernate/Struts/JDK等源码的方法
    【KMS】查看Windows的环境变量
    【KMS】如何预防用户多次点击提交按钮
    MyEclipse中选择一行的快捷键
  • 原文地址:https://www.cnblogs.com/excellent-zzy/p/12404533.html
Copyright © 2011-2022 走看看