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

    说明

    对于所有测试数据,1<=n<=2*10^5,0<=ai,bi,xi<10^5,1<=li<=ri<=n(1<=i<=m);1<=m<=10^5

    Solution:

      本题伪trie树真主席树。

      题目很容易让人往可持久化trie上想,然后就gg了。

      查询区间是否存在某数,想到用主席树实现。

      我们对于每次询问,设置查询的值域区间$[L,R]$(初始$L=0,R=2^{18}-1$),那么还是贪心由$b$从高位往低位判断, 若第$i$位为$1$,则我们要查询在$[l,r]$中是否存在$[L-x,R-x-2^i]$范围内的数(这些数显然$+x$后第$i$位为$0$),然后根据查询情况调整值域区间的范围,第$i$位为$0$情况同理分析就好了。

    代码:

    /*Code by 520 -- 9.30*/
    #include<bits/stdc++.h>
    #define il inline
    #define ll long long
    #define RE register
    #define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++)
    #define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--)
    using namespace std;
    const int N=200005;
    int n,m,a[N],rt[N],cnt,maxn;
    struct node{
        int ls,rs,tot;
    }t[N*40];
    
    int gi(){
        int a=0;char x=getchar();
        while(x<'0'||x>'9') x=getchar();
        while(x>='0'&&x<='9') a=(a<<3)+(a<<1)+(x^48),x=getchar();
        return a;    
    }
    
    il void up(int rt){t[rt].tot=t[t[rt].ls].tot+t[t[rt].rs].tot;}
    
    void ins(int v,int l,int r,int lst,int &rt){
        t[rt=++cnt]=t[lst];
        if(l==r) {t[rt].tot++;return;}
        int m=l+r>>1;
        if(v<=m) ins(v,l,m,t[lst].ls,t[rt].ls);
        else ins(v,m+1,r,t[lst].rs,t[rt].rs);
        up(rt);
    }
    
    int query(int L,int R,int l,int r,int lst,int rt){
        if(R<0||L>maxn) return 0;
        if(L<=l&&R>=r) return t[rt].tot-t[lst].tot;
        int m=l+r>>1,sum=0;
        if(L<=m) sum+=query(L,R,l,m,t[lst].ls,t[rt].ls);
        if(R>m) sum+=query(L,R,m+1,r,t[lst].rs,t[rt].rs);
        return sum;
    }
    
    int main(){
        n=gi(),m=gi();
        For(i,1,n) a[i]=gi(),maxn=max(maxn,a[i]);
        memset(&t[0],0,sizeof(t[0]));
        For(i,1,n) ins(a[i],0,maxn,rt[i-1],rt[i]);
        int b,x,l,r,L,R;
        while(m--){
            b=gi(),x=gi(),l=gi(),r=gi();
            L=0,R=(1<<18)-1;
            Bor(i,0,17)
            if(b&(1<<i)){
                if(query(L-x,R-(1<<i)-x,0,maxn,rt[l-1],rt[r])) R-=(1<<i);
                else L+=(1<<i);    
            }
            else {
                if(query(L+(1<<i)-x,R-x,0,maxn,rt[l-1],rt[r])) L+=(1<<i);
                else R-=(1<<i);    
            }
            printf("%d
    ",L^b);
        }
        return 0;
    }
  • 相关阅读:
    Python匹马行天下之_循环
    Hello world!
    Python匹马天下行之python基本语法
    Python匹马行天下之python之父
    Python匹马行天下之面向对象
    Python匹马行天下之运算符
    Python匹马行天下之初识python!
    跨域问题学习记录 CORS解决的2种方法
    Linux系统运维成长记
    关于倒计时new Date().getTime()出现NaN
  • 原文地址:https://www.cnblogs.com/five20/p/9746547.html
Copyright © 2011-2022 走看看