【loj2985】【WC2019】I君的商店

题目

交互题;

\(n\)个物品,每个物品的价格为0或者1;

给出为1的物品的个数奇偶性k,并保证至少有一个价格为1;

每次可以询问一个集合S的另一个集合T的价值和的大小,交互库会返回>=或者<=;

一次交互的代价为|S|+|T|,总阈值为M;

问每个物品的价值;

\(n \le 10^5 \ , \ M = 500100 \ , \ K=0/1\); 

题解

  • 利用\(2N\)次找出最大的数,即1

    接下来对于\(x \le y\),如果\(x+y\le 1\) ,则\(x=0\),否则\(y=1\)

    复杂度:\(O(7N)\) ;

  • 随便找一个\(z\),比较\(x+y\)\(z\)
    \(x+y \le z\) , 则\(x = 0\)

    \(x+y \ge z\),则\(y \ge z\),用\(y\)去替代\(z\)

    最后会的到很多0和一条单调递增的链,同时最后\(max(x,z) = 1\),得到一个1;

    根据sub3的做法在链上二分,利用奇偶性判断\(mid\)位置的答案;

    复杂度:\(O(5N+ 3log \ N)\) ;

    #include "shop.h"
    #include<bits/stdc++.h>
    using namespace std;
    const int N=100010;
    int st[N],top,q1[N],t1,q2[N],t2;
    bool cmp1(int a,int b){
      q1[0]=a,q2[0]=b;
      return query(q1,1,q2,1);
    }
    bool cmp2(int a,int b,int c){
      q1[0]=a,q1[1]=b;q2[0]=c;
      return query(q1,2,q2,1);
    }
    void swp(int&a,int&b){if(!cmp1(a,b))swap(a,b);}
    void find_price(int id,int n,int k,int ans[]){
      top=0;
      if(n==1){ans[0]=k;return;}
      if(n==2){
          int x=0,y=1;swp(x,y);
          if(k)ans[y]=1,ans[x]=0;
          else ans[x]=ans[y]=1;
          return ;
      }
      if(id==3){
          if(!cmp1(0,n-1)){
              int l=1,r=n-1;
              while(l<r){
                  int mid=l+r>>1;
                  if(cmp2(mid-1,mid,0))r=mid;
                  else l=mid+1;
              }
              --l;
              for(int i=0;i<l;++i)ans[i]=1;
              for(int i=l+1;i<n;++i)ans[i]=0;
              k^=l&1;ans[l]=k;
              return ;
          }
          int l=0,r=n-2;
          while(l<r){
              int mid=l+r>>1;
              if(cmp2(mid,mid+1,n-1))l=mid+1;
              else r=mid;
          }
          for(int i=0;i<l;++i)ans[i]=0;
          for(int i=l+1;i<n;++i)ans[i]=1;
          k^=(n-1-l)&1;ans[l]=k;
          return ;
      }
      int x=0,y,z=1;
      for(int i=2;i<n;++i){
          y=i;swp(x,y);
          if(cmp2(x,y,z)){ans[x]=0;x=y;}
          else {st[++top]=z;z=y;}
      }
      swp(x,z);ans[z]=1;
      if(!top){ans[x]=!k;return;}
      st[++top]=z;
      int l=1,r=top-1;
      while(l<r){
          int mid=l+r>>1;
          if(cmp2(st[mid],st[mid+1],z))l=mid+1;
          else r=mid;
      }
      for(int i=1;i<l;++i)ans[st[i]]=0;
      for(int i=l+1;i<=top;++i)ans[st[i]]=1;
      y=st[l];k^=(top-l)&1;swp(x,y);
      if(cmp2(x,y,z)){ans[x]=0;ans[y]=k;}
      else {ans[y]=1;ans[x]=!k;}
      return ;
    }

转载于:https://www.cnblogs.com/Paul-Guderian/p/10801601.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值