zoukankan      html  css  js  c++  java
  • [Scoi2016]美味

    题意

    4571: [Scoi2016]美味

    Time Limit: 30 Sec  Memory Limit: 256 MB
    Submit: 1048  Solved: 612
    [Submit][Status][Discuss]

    Description

    一家餐厅有 n 道菜,编号 1...n ,大家对第 i 道菜的评价值为 ai(1≤i≤n)。有 m 位顾客,第 i 位顾客的期
    望值为 bi,而他的偏好值为 xi 。因此,第 i 位顾客认为第 j 道菜的美味度为 bi XOR (aj+xi),XOR 表示异或
    运算。第 i 位顾客希望从这些菜中挑出他认为最美味的菜,即美味值最大的菜,但由于价格等因素,他只能从第 
    li 道到第 ri 道中选择。请你帮助他们找出最美味的菜。

    Input

    第1行,两个整数,n,m,表示菜品数和顾客数。
    第2行,n个整数,a1,a2,...,an,表示每道菜的评价值。
    第3至m+2行,每行4个整数,b,x,l,r,表示该位顾客的期望值,偏好值,和可以选择菜品区间。
    1≤n≤2×10^5,0≤ai,bi,xi<10^5,1≤li≤ri≤n(1≤i≤m);1≤m≤10^5

    Output

     输出 m 行,每行 1 个整数,ymax ,表示该位顾客选择的最美味的菜的美味值。

    Sample Input

    4 4
    1 2 3 4
    1 4 1 4
    2 3 2 3
    3 2 3 3
    4 1 2 4

    Sample Output

    9
    7
    6
    7

    HINT

    Source

    [Submit][Status][Discuss]
    
    HOME Back

    分析

    考试的时候一看到异或和就想到Trie,然后就想着用可持久化Trie搞一搞,但是那个加法我推不出来二进制位的变化规律。

    后来才知道这种题的另一种做法,找范围。贪心地从高到低考虑(b)的每一位,我们尽量让他取反,假设最后选出来的(a+x)(ans),那么答案就是(b XOR ans)

    那么假设前面的位置找出来的存在了(ans)里面,现在我们想让第(i)位取成(to),那么这个数值可能的范围是后面的位置全取0到后面的位置全取1。具体而言,就是找有没有以下范围的数:

    [[ans+tocdot 2^i,ans+tocdot 2^i +2^i-1] ]

    那么用主席树就可以解决区间查询存在性问题了。由于对每个(a)加了(x),所以找的范围端点要减去(x)

    时间复杂度(O(n log n +m log^2n))

    代码

    主席树要开到(N*18),也就是(N*(lceil log_2 N ceil+1)),尽管(b<10^5),只有17位,但是(a+x < 2 imes 10^5),有18位,所以(b)要考虑18位,而不是17位。

    #include<bits/stdc++.h>
    #define rg register
    #define il inline
    #define co const
    template<class T>il T read(){
        rg T data=0,w=1;
        rg char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-') w=-1;
            ch=getchar();
        }
        while(isdigit(ch))
            data=data*10+ch-'0',ch=getchar();
        return data*w;
    }
    template<class T>il T read(rg T&x){
        return x=read<T>();
    }
    typedef long long ll;
    using namespace std;
    
    co int N=2e5+1;
    int root[N],tot,s[N*18],L[N*18],R[N*18];
    void insert(int&x,int l,int r,int p){
    	++tot,s[tot]=s[x]+1,L[tot]=L[x],R[tot]=R[x],x=tot;
    	if(l==r) return;
    	int mid=l+r>>1;
    	if(p<=mid) insert(L[x],l,mid,p);
    	else insert(R[x],mid+1,r,p);
    }
    int query(int x,int y,int l,int r,int ql,int qr){
    	if(qr<l||ql>r||!x&&!y) return 0;
    	if(ql<=l&&r<=qr) return s[y]-s[x];
    	int mid=l+r>>1;
    	if(qr<=mid) return query(L[x],L[y],l,mid,ql,qr);
    	if(ql>mid) return query(R[x],R[y],mid+1,r,ql,qr);
    	return query(L[x],L[y],l,mid,ql,qr)+query(R[x],R[y],mid+1,r,ql,qr);
    }
    int main(){
    //	freopen("food.in","r",stdin),freopen("food.out","w",stdout);
    	int n=read<int>(),m=read<int>();
    	for(int i=1;i<=n;++i) insert(root[i]=root[i-1],0,99999,read<int>());
    	for(int b,x,l,r,ans;m--;){
    		read(b),read(x),read(l),read(r),ans=0;
    		for(int i=17,to;i>=0;--i){
    			to=~b>>i&1;
    			ans+=(query(root[l-1],root[r],0,99999,ans+(to<<i)-x,ans+(to<<i)+(1<<i)-1-x)?to:!to)<<i;
    		}
    		printf("%d
    ",b^ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    (十)条件判断
    (九)字符处理命令
    (八)awk命令
    (六)环境变量配置文件
    (七)grep命令行提取符号
    Ⅶ 类模板与STL编程 ②
    Ⅵ 虚函数与多态性
    Ⅴ 运算符重载
    Ⅳ 继承与派生②
    Ⅳ 继承与派生①
  • 原文地址:https://www.cnblogs.com/autoint/p/10495273.html
Copyright © 2011-2022 走看看