• CF 914D 线段树维护区间gcd == x


    题目大意

    给定一个序列,支持两种操作:

    • 单点修改
    • 区间查询:是否存在一种方案,使得修改区间种0/1个元素后使得区间\(gcd = x\)

    \(n \leq 5 \times 10^5\)

    思路

    查询时,记query函数返回值为当前区间至少修改多少个元素使得区间gcd是x的倍数。

    查询时,对于每个区间只需要找到一个不是x的倍数的数字即可。

    复杂度\(O(nlogn)\)

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 5e5 + 10;
    
    int n;
    int a[N];
    struct node {
    	int l,r;
    	int gcd;
    }t[N << 2];
    
    int gcd(int a,int b) {
    	return b == 0 ? a : gcd(b,a % b);
    }
    
    void update(int rt) {
    	int ch = rt << 1;
    	t[rt].gcd = gcd(t[ch].gcd,t[ch + 1].gcd);
    }
    
    void build(int l,int r,int rt) {
    	t[rt].l = l;
    	t[rt].r = r;
    	if(l == r) {
    		t[rt].gcd = a[l];
    		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 x,int rt,int v) {
    	if(t[rt].l == t[rt].r) {
    		t[rt].gcd = v;
    		return;
    	}
    	int mid = (t[rt].l + t[rt].r) >> 1;
    	int ch = rt << 1;
    	if(x <= mid) modify(x,ch,v);
    	else modify(x,ch + 1,v);
    	update(rt);
    }
    
    int query(int l,int r,int rt,int x) {
    	if(t[rt].gcd % x == 0) return 0;
    	if(l == t[rt].l and r == t[rt].r) {
    		if(l == r) return 1;
    		int ch = rt << 1;
    		if(t[ch].gcd % x == 0) {
    			return query(t[ch + 1].l,t[ch + 1].r,ch + 1,x);
    		}
    		if(t[ch + 1].gcd % x == 0) {
    			return query(t[ch].l,t[ch].r,ch,x);
    		}
    		return 2;
    	}
    	int ch = rt << 1;
    	int mid = (t[rt].l + t[rt].r) >> 1;
    	if(r <= mid) {
    		return query(l,r,ch,x);
    	}else if(l > mid) {
    		return query(l,r,ch + 1,x);
    	}else {
    		return query(l,mid,ch,x) + query(mid + 1,r,ch + 1,x);
    	}
    }
    
    int main () {
    	scanf("%d",&n);
    	for (int i = 1;i <= n; i ++) {
    		scanf("%d",&a[i]);
    	}
    	build(1,n,1);
    	int q;
    	cin >> q;
    	while(q --) {
    		int op;
    		scanf("%d",&op);
    		if(op == 1) {
    			int l,r,x;
    			scanf("%d %d %d",&l,&r,&x);
    			int ans = query(l,r,1,x);
    			if(ans <= 1) {
    				puts("YES");
    			}else puts("NO");
    		}
    		else {
    			int x,y;
    			scanf("%d %d",&x,&y);
    			modify(x,1,y);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    移植spdylay到libcurl
    用到的C++标准库
    libcurl底层调用逻辑
    socket编程
    linux的一些机制Signal, Fork,
    openssl 编程
    对称加密,非对称加密
    ajax提交整个form表单
    一道基础的for语句js编译过程
    怎样将浏览器一句话变为文本编辑器
  • 原文地址:https://www.cnblogs.com/Allorkiya/p/15890137.html
Copyright © 2020-2023  润新知