• CF 920F 区间求约数个数


    题目大意

    给定一个序列,支持区间每个元素变为它们的约数个数、区间求和

    \(n \leq 10^5,a_i \leq 10^9\)

    思路

    由于\(a_i \leq 10^9\),因此每一个元素最多会被修改有限次就会变为1或2,复杂度\(O(nlogn)\)

    代码

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    
    const int N = 3e5 + 10;
    const int M = 1e6 + 10;
    int a[N];
    int Ans[M];
    void sieve () {
    	for(int i = 1;i <= M - 10; i ++) {
    		for(int j = i;j <= M - 10;j += i) {
    			Ans[j] ++;
    		}
    	}
    }
    
    struct node {
    	int l,r;
    	ll sum;
    	int tag;
    }t[N << 2];
    
    void update(int rt) {
    	int ch = rt << 1;
    	t[rt].sum = t[ch].sum + t[ch + 1].sum;
    	t[rt].tag = (t[ch].tag && t[ch + 1].tag);
    }
    void build(int l,int r,int rt) {
    	t[rt].l = l;
    	t[rt].r = r;
    	if(l == r) {
    		t[rt].sum = a[l];
    		t[rt].tag = (a[l] <= 2); //是质数为1,意味着不可以继续进行分解
    		return;
    	}
    	int mid = (l + r) >> 1;
    	int ch = rt << 1;
    	build(l,mid,ch);
    	build(mid + 1,r,ch + 1);
    	update(rt);
    }
    
    
    void modify(int l,int r,int rt) {
    	if(t[rt].tag) return;
    	if(t[rt].l == t[rt].r) {
    		t[rt].sum = Ans[t[rt].sum];
    		t[rt].tag = (t[rt].sum <= 2);
    		return;
    	}
    	int mid = (t[rt].l + t[rt].r) >> 1;
    	int ch = rt << 1;
    	if(r <= mid) {
    		modify(l,r,ch);
    	}else if(l > mid) {
    		modify(l,r,ch + 1);
    	}else {
    		modify(l,mid,ch);
    		modify(mid + 1,r,ch + 1);
    	}
    	update(rt);
    }
    
    ll query(int l,int r,int rt) {
    	if(l == t[rt].l and r == t[rt].r) return t[rt].sum;
    	int mid = (t[rt].l + t[rt].r) >> 1;
    	int ch = rt << 1;
    	ll res = 0;
    	if(r <= mid) {
    		res += query(l,r,ch);
    	}else if(l > mid) {
    		res += query(l,r,ch + 1);
    	}else {
    		res += query(l,mid,ch) + query(mid + 1,r,ch + 1);
    	}
    	//cout << "#:" << l << ' ' << r << ' ' << res << endl;
    	return res;
    }
    
    int n,m;
    int main () {
    	sieve();
    	scanf("%d %d",&n,&m);
    	for (int i = 1;i <= n; i ++) {
    		scanf("%d",&a[i]);
    	}
    	build(1,n,1);
    	while(m --) {
    		int t,l,r;
    		scanf("%d %d %d",&t,&l,&r);
    		if(t == 1) {
    			modify(l,r,1);
    		}
    		else {
    			printf("%lld\n",query(l,r,1));
    		}
    	}
    	return 0;
    }
    /*
    7 6
    6 4 1 10 3 2 4
    2 1 7
    2 4 5
    1 3 5
    2 4 4
    1 5 7
    2 1 7
    
    */
    
  • 相关阅读:
    ASP.NET 使用Ajax(转)
    使用Docker,很多坑(之一):在windows中使用
    .NET Core 各种学习资源
    docker-compose.yml配置文件详解(转)
    英雄无敌王国刷将脚本
    Valid format values for declare-styleable/attr tags[转]
    no Session问题,即延迟加载
    适配器模式--Adapter Pattern
    策略模式--Strategy
    装饰模式--Decorator Pattern
  • 原文地址:https://www.cnblogs.com/Allorkiya/p/15890525.html
Copyright © 2020-2023  润新知