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

    题目描述

    一家餐厅有 n 道菜,编号 1...n ,大家对第 i 道菜的评价值为 ai(1<=i<=n)。有 m 位顾客,第 i 位顾客的期望值为 bi,而他的偏好值为 xi 。因此,第 i 位顾客认为第 j 道菜的美味度为 bi XOR (aj+xi),XOR 表示异或运算。

    第 i 位顾客希望从这些菜中挑出他认为最美味的菜,即美味值最大的菜,但由于价格等因素,他只能从第 li 道到第 ri 道中选择。请你帮助他们找出最美味的菜。

    输入输出格式

    输入格式:

    第1行,两个整数,n,m,表示菜品数和顾客数。

    第2行,n个整数,a1,a2,...,an,表示每道菜的评价值。

    第3至m+2行,每行4个整数,b,x,l,r,表示该位顾客的期望值,偏好值,和可以选择菜品区间。

    输出格式:

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

    输入输出样例

    输入样例#1: 复制

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

    输出样例#1: 复制

    9 
    7 
    6 
    7

    看到这种区间XOR最大值我们一般想到可持久化Trie。但这道题是bi XOR (aj+xi),而不是bi XOR aj,就不能用Trie了。

    但是我们依然按照套路,从高位开始贪心。假设之前我们已经得到了大小为last的数,现在处理第i位。假设b[i]第i位为0,那么我们就要找一个(aj+xi)且它第i位为1。那么(aj+xi)的范围就是[last+(1<<i),last+(1<<i+1)-1]。所以现在问题变成了询问一段区间内某个范围内的数的存在情况,于是用主席树来维护。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<set>
    #include<map>
    #include<vector>
    #include<ctime>
    #define ll long long
    #define N 200005
    
    using namespace std;
    inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}
    
    int n,m;
    int ls[N*50],rs[N*50];
    int num[N*50];
    const int lx=0,rx=1e6;
    int rt[N],cnt;
    void Insert(int &now,int old,int lx,int rx,int f) {
    	now=++cnt;
    	num[now]=num[old];
    	ls[now]=ls[old],rs[now]=rs[old];
    	num[now]++;
    	if(lx==rx) return ;
    	int mid=lx+rx>>1;
    	if(f<=mid) Insert(ls[now],ls[old],lx,mid,f);
    	else Insert(rs[now],rs[old],mid+1,rx,f);
    }
    
    int query(int u,int v,int l,int r,int lx,int rx) {
    	if(lx>r||rx<l) return 0;
    	if(!u&&!v) return 0;
    	if(l<=lx&&rx<=r) {
    		return num[v]-num[u];
    	}
    	int mid=lx+rx>>1;
    	return query(ls[u],ls[v],l,r,lx,mid)+query(rs[u],rs[v],l,r,mid+1,rx);
    }
    
    int main() {
    	n=Get(),m=Get();
    	int a,x,l,r;
    	rt[0]=++cnt;
    	for(int i=1;i<=n;i++) {
    		a=Get();
    		Insert(rt[i],rt[i-1],lx,rx,a);
    	}
    	for(int i=1;i<=m;i++) {
    		a=Get(),x=Get(),l=Get(),r=Get();
    		int ans=0,last=0;
    		for(int j=20;j>=0;j--) {
    			if(a&(1<<j)) {
    				if(query(rt[l-1],rt[r],last-x,last+(1<<j)-1-x,lx,rx)) {
    					ans+=(1<<j);
    				} else last+=(1<<j);
    			} else {
    				if(query(rt[l-1],rt[r],last+(1<<j)-x,last+(1<<j+1)-1-x,lx,rx)) {
    					ans+=(1<<j);
    					last+=(1<<j);
    				}
    			}
    		}
    		cout<<ans<<"
    ";
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    Python包中__init__.py作用
    获取web页面xpath
    Selenium学习(Python)
    C++构造函数的选择
    分布式实时处理系统——C++高性能编程
    构建之法(邹欣)
    分布式实时处理系统——通信基础
    go语言-csp模型-并发通道
    redis.conf 配置说明
    Linux fork()一个进程内核态的变化
  • 原文地址:https://www.cnblogs.com/hchhch233/p/9996740.html
Copyright © 2011-2022 走看看