• [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,表示该位顾客的期望值,偏好值,和可以选择菜品区间。1<=n<=2*10^5,0<=ai,bi,xi<10^5,1<=li<=ri<=n(1<=i<=m);1<=m<=10^5

    输出格式:

    输出 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

    题解:

     一开始看到这题,觉得不可做。

    一看标签,主席树?Impossible!

    于是乎,点开题解堕落。

    既然题目问的是异或值最大,我们不妨来一个贪心,从高位到低位。

    首先按照输入的顺序建立权值主席树。然后将输入的数的位数从高到低的顺序贪心,如果当前区间内有可以让这一位经过异或运算后为1的数,那么就将范围缩小。

     1 //Never forget why you start
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstdlib>
     5 #include<cstring>
     6 #include<cmath>
     7 #include<algorithm>
     8 #define ll(x) seg[x].l
     9 #define rr(x) seg[x].r
    10 using namespace std;
    11 int n,m,ans,a[200005];
    12 int root[200005],cnt;
    13 struct seg{
    14   int l,r,cnt;
    15 }seg[10000005];
    16 int newnode(int root){
    17   cnt++;
    18   seg[cnt].l=seg[root].l;
    19   seg[cnt].r=seg[root].r;
    20   seg[cnt].cnt=seg[root].cnt;
    21   return cnt;
    22 }
    23 void push_up(int root){
    24   seg[root].cnt=seg[ll(root)].cnt+seg[rr(root)].cnt;
    25 }
    26 void insert(int &root,int l,int r,int x){
    27   root=newnode(root);
    28   if(l==r){seg[root].cnt++;return;}
    29   int mid=(l+r)>>1;
    30   if(x<=mid)insert(ll(root),l,mid,x);
    31   if(mid<x)insert(rr(root),mid+1,r,x);
    32   push_up(root);
    33 }
    34 int query(int lroot,int rroot,int left,int right,int l,int r){
    35   if(l<=left&&right<=r)return seg[rroot].cnt-seg[lroot].cnt;
    36   if(l>right||r<left)return 0;
    37   int mid=(left+right)>>1,ans=0;
    38   if(l<=mid)ans+=query(ll(lroot),ll(rroot),left,mid,l,r);
    39   if(mid<r)ans+=query(rr(lroot),rr(rroot),mid+1,right,l,r);
    40   return ans;
    41 }
    42 int main(){
    43   int i,j;
    44   scanf("%d%d",&n,&m);
    45   for(i=1;i<=n;i++){
    46     scanf("%d",&a[i]);
    47     root[i]=root[i-1];
    48     insert(root[i],1,1e5,a[i]);
    49   }
    50   for(i=1;i<=m;i++){
    51     int b,x,l,r;
    52     ans=0;
    53     scanf("%d%d%d%d",&b,&x,&l,&r);
    54     for(j=17;j>=0;j--){
    55       int now=ans+((1^((b>>j)&1))<<j);
    56       if(query(root[l-1],root[r],1,1e5,now-x,now+(1<<j)-1-x))ans=now;
    57       else ans+=((b>>j)&1)<<j;
    58     }
    59     printf("%d
    ",ans^b);
    60   }
    61   return 0;
    62 }
  • 相关阅读:
    spring 包的依赖关系
    菜鸟程序猿之IDEA快捷键
    eclipse的svn插件
    SVN使用教程总结
    Oracle 11g安装步骤详谈
    C3P0连接池的配置与使用
    Java课程设计
    201621123057 《Java程序设计》第14周学习总结
    201621123057 《Java程序设计》第13周学习总结
    201621123057 《Java程序设计》第12周学习总结
  • 原文地址:https://www.cnblogs.com/huangdalaofighting/p/8257402.html
Copyright © 2020-2023  润新知