zoukankan      html  css  js  c++  java
  • Codeforces972 D. Kuro and GCD and XOR and SUM 01Trie

    本题链接:CF972 D. Kuro and GCD and XOR and SUM

    题目大意

    (n)个询问,每个询问形如如下两种:

    • 增加一个数(x)到一开始为空的序列中.
    • 给定三个参数(x,k,s).要求在序列找一个数(v)满足(k | gcd(x,v)),(x + v leq s),(x oplus v)最大.如果不存在这样的(v)则输出(-1).

    数据范围:

    (1 leq q leq 10^5)

    (1 leq x,k,s leq 10^5).

    思路

    显然(gcd)这个条件的约束性可比什么求和强多了,先对这玩意下手.注意到(k | gcd(x,v))事实上跟一般的条件不大一样,他其实只是满足:(k | x)以及(k | x)而已.所以对于每个询问可以先排除掉一种无解情况:即(x)不是(k)的倍数的时候.接下来其实只用找(k)的倍数(v)了.

    不过有一点需要分开讨论:如果(k=1)此时的倍数太多了,所以我们不妨只讨论(k=1)的情况以及(k eq 1)的情况:

    • (k=1),那么必然有(k|v),此时只需要找一个在序列里面的数(v)满足(x+vleq s)就可以满足有解的存在了,之后就需要满足(x oplus v)最大,这个可以用一个Trie来做,模型还是比较典型的插入数以及查询.那么为了满足不等式条件,我们只需要对每个在Trie上的点额外打一个最小值标记表示在这个点下最小的值是多少,如果最小值标记都不能满足不等式关系,那么说明:在这个点之下无论在怎么去找都找不到一个合法的点了,只能尝试另外一边的点是否合法,如果都走不通就说明不存在点.贪心去找就可以了.
    • 枚举(z=k)的若干倍,满足(z+x leq s).在这种情况下,我们只需要查询在Trie上是否存在着这个(z)就可以了.更新最大的异或值,维护对应的答案即可.

    (感觉复杂度有点玄幻)

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define forn(i,x,n) for(int i = x;i <= n;++i)	
    
    const int N = 1e5+7,M = 24;
    int tr[N * M][2],idx,dwtag[N * M];
    
    void insert(int v)
    {
    	int p = 0;
    	for(int i = M;i >= 0;--i)
    	{
    		int k = v >> i & 1;
    		if(!tr[p][k])	tr[p][k] = ++idx;
    		p = tr[p][k];
    		dwtag[p] = min(v,(dwtag[p] == 0 ? v : dwtag[p]));
    	}
    }
    
    int query(int x,int limit)
    {
    	int p = 0;
    	for(int i = M;i >= 0;--i)
    	{
    		int o = tr[p][x >> i & 1],r = tr[p][!(x >> i & 1)];
    		if(dwtag[o] + x > limit && dwtag[r] + x > limit) return -1;
    		if(dwtag[r] + x <= limit)	p = r;
    		else p = o;
    	}
    	return dwtag[p];
    }
    
    int query(int x)
    {
    	int p = 0;
    	for(int i = M;i >= 0;--i)
    	{
    		p = tr[p][x >> i & 1];
    		if(!p)	return 0;
    	}	
    	return p;
    }
    
    int main() 
    {
    	dwtag[0] = 1e9;
    	int q;scanf("%d",&q);
    	while(q--)
    	{
    		int t;scanf("%d",&t);
    		if(t == 1)
    		{
    			int x;scanf("%d",&x);
    			insert(x);
    		}
    		else
    		{
    			int x,k,s;scanf("%d%d%d",&x,&k,&s);
    			if(x % k)	puts("-1");
    			else
    			{
    				if(k == 1)	printf("%d
    ",query(x,s));
    				else
    				{
    					int resx = -1e9,resv = -1;
    					for(int z = k;x + z <= s;z += k)
    						if(query(z))
    						{
    							if((z ^ x) > resx)
    							{
    								resx = z ^ x;
    								resv = z;
    							}
    						}
    					printf("%d
    ",resv);
    				}
    			}
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    委托与事件的关系
    分布式存储ceph——(1)部署ceph
    neutron二
    openstack第五章:cinder
    openstack第六章:dashboard
    openstack第一章:keystone
    openstack第二章:glance
    openstack第三章:nova
    openstack第四章:neutron— 网络服务
    openstack安装
  • 原文地址:https://www.cnblogs.com/HotPants/p/14398810.html
Copyright © 2011-2022 走看看