zoukankan      html  css  js  c++  java
  • [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


    题解

    先不考虑那个(+x)
    我们显然要贪心的从高位向低位决策
    那么我们已经贪心的处理完了前(i-1)位,这时候的答案是(k)
    假设这一位的(b)(0)
    那么我们只需要查询([k+2^i,k+2^i+2^i-1])这个值域区间存不存在数即可
    然后对于那个(+x),就相当于每次查询值的时候减掉(x)
    也就是说最后对于每一位查询的值域区间是([k+2^i-x,k+2^i+2^i-1-x])

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    const int M = 200005 ;
    using namespace std ;
    
    inline int read() {
    	char c = getchar() ; int x = 0 , w = 1 ;
    	while(c>'9'||c<'0') { if(c=='-') w = -1 ; c = getchar() ; }
    	while(c>='0'&&c<='9') { x = x*10+c-'0' ; c = getchar() ; }
    	return x*w ;
    }
    
    int n , m , upp = 200000 , tot , val[M] , rt[M] ;
    struct Node { int l , r , sum ; } t[M * 20] ;
    void Insert(int x , int l , int r , int &now , int pre) {
    	now = ++ tot ; t[now] = t[pre] ; t[now].sum ++ ;
    	if(l == r) return ; int mid = (l + r) >> 1 ;
    	if(mid >= x) Insert(x , l , mid , t[now].l , t[pre].l) ;
    	else Insert(x , mid + 1 , r , t[now].r , t[pre].r) ;
    }
    int query(int i , int j , int L , int R , int l , int r) {
    	if(l >= L && r <= R) return t[j].sum - t[i].sum ; int mid = (l + r) >> 1 ;
    	if(mid >= R) return query(t[i].l , t[j].l , L , R , l , mid) ;
    	else if(mid < L) return query(t[i].r , t[j].r , L , R , mid + 1 , r) ;
    	else return query(t[i].l , t[j].l , L , mid , l , mid) + query(t[i].r , t[j].r , mid + 1 , R , mid + 1 , r) ;
    }
    int main() {
    	n = read() ; m = read() ;
    	for(int i = 1 ; i <= n ; i ++) {
    		val[i] = read() ;
    		Insert(val[i] , 0 , upp , rt[i] , rt[i - 1]) ;
    	}
    	while(m --) {
    		int b = read() , x = read() , l = read() , r = read() , ans = 0 ;
    		for(int i = 18 ; i >= 1 ; i --) {
    			bool dlt = (b & (1 << (i - 1))) ; dlt ^= 1 ;
    			if(query( rt[l - 1] , rt[r] , ans + dlt * (1 << (i - 1)) - x , ans + dlt * (1 << (i - 1)) + (1 << (i - 1)) - 1 - x , 0 , upp ))
    				ans = ans + dlt * (1 << (i - 1)) ;
    			else ans = ans + (dlt ^ 1) * (1 << (i - 1)) ;
    		}
    		printf("%d
    ",ans ^ b) ;
    	}
    	return 0 ;
    }
    
  • 相关阅读:
    个人网址收集
    使用 TListView 控件(2)
    C# 语法练习(14): 类[六] 事件
    如何在 "万一的 Delphi 博客" 回复自动格式化的着色代码?
    使用 TListView 控件(1)
    C# 语法练习(13): 类[五] 索引器
    使用 TListView 控件(4)
    C# 语法练习(11): 类[三] 构造函数、析构函数、base、this
    C# 语法练习(12): 类[四] 抽象类与抽象成员、密封类与密封成员
    使用 TListView 控件(3)
  • 原文地址:https://www.cnblogs.com/beretty/p/10640288.html
Copyright © 2011-2022 走看看