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

    题目戳这

    Description

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

    Input

    第1行,两个整数(n)(m),表示菜品数和顾客数。
    第2行,(n)个整数,(a_1)(a_2)(...)(a_n),表示每道菜的评价值。
    第3至(m+2)行,每行4个整数(b,x,l,r,)表示该位顾客的期望值,偏好值,和可以选择菜品区间。
    $ 1≤n≤2×10^5,0≤a_i,b_i,x_i<10^5,1≤l_i≤r_i≤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
    

    题解

    首先在区间([l,r])里面选就肯定是主席树了吧。
    然后既然求异或结果最大那么就考虑按位贪心。
    (ans=a_j+x_i),那么我们就希望(ans)在二进制上从高位到低位尽量都与(b_i)不同。我们假设不同,那么就是确定了某一个最高位的数值。假设确定的是第(i)位的数值,那么我们相当于确定了解的范围,即一个长度为(2^i)的区间。接下来就是通过两棵主席树作差找这个范围内是否存在解了。

    code

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N  = 200005;
    struct president_tree{int ls,rs,num;}t[N*25];
    int n,m,a,rt[N],tot,b,x,l,r,L,R,ans,opt;
    int gi()
    {
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    void build(int &now,int l,int r)
    {
    	now=++tot;
    	if (l==r) return;
    	int mid=l+r>>1;
    	build(t[now].ls,l,mid);
    	build(t[now].rs,mid+1,r);
    }
    void update(int &now,int l,int r,int pos)
    {
    	t[++tot]=t[now];
    	t[now=tot].num++;
    	if (l==r) return;
    	int mid=l+r>>1;
    	if (pos<=mid) update(t[now].ls,l,mid,pos);
    	else update(t[now].rs,mid+1,r,pos);
    }
    int Query(int A,int B,int l,int r,int ql,int qr)
    {
    	if (l>=ql&&r<=qr) return t[A].num-t[B].num;
    	int mid=l+r>>1,s=0;
    	if (ql<=mid) s+=Query(t[A].ls,t[B].ls,l,mid,ql,qr);
    	if (qr>mid) s+=Query(t[A].rs,t[B].rs,mid+1,r,ql,qr);
    	return s;
    }
    int main()
    {
    	n=gi();m=gi();
    	build(rt[0],1,N);
    	for (int i=1;i<=n;i++)
    	{
    		a=gi();
    		rt[i]=rt[i-1];
    		update(rt[i],0,N,a);
    	}
    	while (m--)
    	{
    		b=gi();x=gi();l=gi();r=gi();ans=0;
    		for (int i=17;i>=0;i--)
    		{
    			if (b&(1<<i)) L=ans,R=ans+(1<<i)-1,opt=0;
    			else L=ans+(1<<i),R=ans+(1<<i+1)-1,opt=1;
    			if (!Query(rt[r],rt[l-1],0,N,max(0,L-x),min(N,R-x))) opt^=1;
    			ans|=opt<<i;
    		}
    		printf("%d
    ",ans^b);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    想要学习设计模式,你得先会看类图,一张图读懂UML
    UML类图中箭头的含义
    DDD学习
    Customize your build
    WaitAll vs WhenAll
    When does a C# Task actually start?
    UE4中多种颜色轮廓线的后期处理
    [UE4]武器碰撞
    动态材质实例(Dynamic Material Instance)
    卷积运算
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8138043.html
Copyright © 2011-2022 走看看