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

    链接:https://www.luogu.org/problemnew/show/3293

    题意:

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

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

    数据范围:n,m,a[i]<=10e5

    题解:

    很水的一道题啊。。。

    考虑xor运算,每一位都是互相独立的,所以若要总的值越大,即越靠前的位越大

    从前向后考虑每一位,若该位要取1才能得到最大值

    则(aj+xi)的范围应该sum--------sum+(1<<i)-1 {这步最关键}

    则只需查找aj属于sum-a[j]-------sum+(1<<i)-1-a[j]即可

    之后就显然了。。主席树维护

    ****注意优先级要多打括号啊。。。

    代码:

    #include <bits/stdc++.h>
    #define mid (h+t)/2
    #define maxn 100000
    using namespace std;
    struct re{int h,t,x;}p[10000000];
    int n,m,j,now,a[300000],fa[300000],f[100];
    void build(int x,int h,int t)
    {
        now=max(now,x);
        if (h==t) return;
        p[x].h=x*2; p[x].t=x*2+1;
        build(x*2,h,mid); build(x*2+1,mid+1,t);
    };
    void insert(int x,int &y,int num,int h,int t)
    {  
         y=++now,p[y]=p[x]; p[y].x++;
         if (h==t) return;
         if (mid>=num) insert(p[x].h,p[y].h,num,h,mid);
         else insert(p[x].t,p[y].t,num,mid+1,t);
    };
    bool query(int x,int y,int h1,int t1,int h,int t)
    {
        if (t<h1 || t1<h) return(false); 
        if (h1<=h && t<=t1) return((p[y].x-p[x].x)>0);
        return(query(p[x].h,p[y].h,h1,t1,h,mid) || query(p[x].t,p[y].t,h1,t1,mid+1,t));    
    }
    int main(){
        freopen("noip.in","r",stdin);
        freopen("noip.out","w",stdout); 
        cin>>n>>m;
        build(1,1,n); 
        fa[0]=1;
        for (int i=1;i<=n;i++) 
          cin>>a[i],insert(fa[i-1],fa[i],a[i],0,maxn);
        for (j=1;f[j-1]<=100000;j++) f[j]=1<<(j-1);
      int tmp=j-1;
        for (int i=1;i<=m;i++)
        {
            int c1,d1,x,y,ll=0;
            cin>>c1>>d1>>x>>y;
            for (int j=tmp;j>0;j--)
            {
              if ((f[j]&c1)>0)
              {
                if (!query(fa[x-1],fa[y],max(0,ll-d1),ll+f[j]-1-d1,0,maxn))
                  ll+=f[j];
            }
            else 
              if (query(fa[x-1],fa[y],max(0,ll+f[j]-d1),ll+2*f[j]-1-d1,0,maxn))
                ll+=f[j];
            }
            cout<<(c1^ll)<<endl;
      }
    }
  • 相关阅读:
    定义类和类的实例化
    python学习第二天-文件的读写
    python学习第二天 pyhon字符串操作
    PYTHON的元组和字典丶深拷贝丶浅拷贝丶集合的常用操作方法
    python 数组的常识操作和切片
    Python字符串、集合练习_密码校验
    Python字典练习_注册校验
    获取随机的字符串
    PHP 阿拉伯数字转中文表述
    小程序发送验证码倒计时
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/8025535.html
Copyright © 2011-2022 走看看