1. 程式人生 > >P3293 [SCOI2016]美味

P3293 [SCOI2016]美味

clu include register get eof tro 整數 輸出 col

題目描述

一家餐廳有 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}$),那麽還是貪心由$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\n",L^b); } return 0; }

P3293 [SCOI2016]美味