zoukankan      html  css  js  c++  java
  • Bash and a Tough Math Puzzle CodeForces 914D 线段树+gcd数论

    Bash and a Tough Math Puzzle CodeForces 914D 线段树+gcd数论

    题意

    给你一段数,然后小明去猜某一区间内的gcd,这里不一定是准确值,如果在这个区间内改变一个数的值(注意不是真的改变),使得这个区间的gcd是小明所猜的数也算小明猜对。另一种操作就是真的修改某一点的值。

    解题思路

    这里我们使用线段树,维护区间内的gcd,判断的时候需要判断这个区间的左右子区间的gcd是不是小明猜的数的倍数或者就是小明猜的数,如果是,那么小明猜对了。否则就需要进入这个区间再进行判断,如果一直递归到叶子节点的话就要使ans++,代表需要改变的点的个数,如果ans大于1就可以直接结束当前层次的查询,因为小明已经猜错了。

    具体看query代码

    代码实现

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define ls (rt<<1)
    #define rs (rt<<1|1)
    using namespace std;
    const int maxn=5e5+7;
    struct node{
    	int l, r;
    	int gcd;
    }t[maxn<<2];
    int num[maxn];
    int n, m, ans;
    int gcd(int x, int y)
    {
    	if(y==0) return x;
    	return gcd(y, x%y);
    }
    void up(int rt)
    {
    	t[rt].gcd=gcd(t[ls].gcd, t[rs].gcd);
    }
    void build(int rt, int l, int r)
    {
    	t[rt].l=l;
    	t[rt].r=r;
    	if(l==r)
    	{
    		t[rt].gcd=num[l];
    		return ;
    	}
    	int mid=(l+r)>>1;
    	build(ls, l, mid);
    	build(rs, mid+1, r);
    	up(rt);
    }
    void update(int rt, int x, int y)
    {
    	if(t[rt].l==t[rt].r)
    	{
    		t[rt].gcd=y;
    		return ;
    	}
    	int mid=(t[rt].l+t[rt].r)>>1;
    	if(x<=mid) update(ls, x, y);
    	else update(rs, x, y);
    	up(rt);
    }
    void query(int rt, int l, int r, int x)
    {
    	if(t[rt].l==t[rt].r)//如果递归到了叶子节点,那么说明如果需要小明猜对,那么这个点的值就需要修改。
    	{
    		ans++; //表示需要修改的点的个数。
    		return ;
    	}
    	if(ans > 1) return ; //如果大于1的话就直接返回,不用再进行查询了。
    	int mid=(t[rt].l+t[rt].r)>>1;
    	if(l<=mid && t[ls].gcd%x!=0) query(ls, l, r, x);
    	if(r>mid && t[rs].gcd%x!=0) query(rs, l, r, x);		
    }
    int main()
    {
    	while(scanf("%d", &n)!=EOF)
    	{
    		for(int i=1; i<=n; i++)
    			scanf("%d", &num[i]);
    		build(1, 1, n);
    		scanf("%d", &m);
    		int op, l, r, x, y;
    		for(int i=1; i<=m; i++)
    		{
    			scanf("%d", &op);
    			if(op==1)
    			{
    				scanf("%d%d%d", &l, &r, &x);
    				ans=0;
    				query(1, l, r, x);
    				if(ans>1) printf("NO
    ");
    				else printf("YES
    ");
    			}
    			else 
    			{
    				scanf("%d%d", &x, &y);
    				update(1, x, y);
    			}
    		}
    	}	
    	return 0;
    } 
    
    欢迎评论交流!
  • 相关阅读:
    poj 3616 Milking Time
    poj 3176 Cow Bowling
    poj 2229 Sumsets
    poj 2385 Apple Catching
    poj 3280 Cheapest Palindrome
    hdu 1530 Maximum Clique
    hdu 1102 Constructing Roads
    codeforces 592B The Monster and the Squirrel
    CDOJ 1221 Ancient Go
    hdu 1151 Air Raid(二分图最小路径覆盖)
  • 原文地址:https://www.cnblogs.com/alking1001/p/11406145.html
Copyright © 2011-2022 走看看