• 【题解】[SCOI2016]美味


    [SCOI2016]美味

    ( ext{Solution:})

    第一种感觉是可持久化 Trie 的样子。但是如果这样做, (x) 的限制是没有办法消去的。

    这里陷入了某种错误的思考状态,发现 Trie 上分类讨论无果,从题解中学到了另一种做法:

    Trie 树的本质是每一个节点下的子树都代表了一个值域。我们联想到,主席树同样可以是值域线段树,它也可以代表一个值域。

    那能不能用更普遍的主席树去代替 Trie 呢?

    考虑对于 (b) 的某二进制位的取值, (a[i]) 应该取什么。

    那么,若 (b) 的第 (i) 位为 (1) 那么 (a[i]) 这一位是 (0) 更优秀。

    那么,令当前找到的最优结果是 (A,) (ain{[A-x,A+(1<<i)-1-x]}) 这样使得 (a+x) 的对应二进制位一定非 (1).

    其他情况类似。

    那么我们就得到了需要的 (a) 的值域! 而前文我们恰好对 (a) 以值域建立了主席树。

    于是,在主席树上查询即可。复杂度 (O(mlog^2 v).)

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN=5e5+10;
    const int M=(1<<25);
    struct Tr{int ls,rs,sum;}tr[MAXN<<5];
    int node,rt[MAXN],n,m,a[MAXN];
    inline int Min(int x,int y){return x<y?x:y;}
    inline int Max(int x,int y){return x>y?x:y;}
    inline int read() {
    	int s=0,w=1;
    	char ch=getchar();
    	while(!isdigit(ch)) {
    		if(ch=='-')w=-1;
    		ch=getchar();
    	}
    	while(isdigit(ch)) {
    		s=s*10-48+ch;
    		ch=getchar();
    	}
    	return w*s;
    }
    int change(int x,int l,int r,int pos,int v){
    	int p=++node;
    	tr[p]=tr[x];
    	tr[p].sum+=v;
    	if(l==r)return p;
    	int mid=(l+r)>>1;
    	if(pos<=mid)tr[p].ls=change(tr[p].ls,l,mid,pos,v);
    	else tr[p].rs=change(tr[p].rs,mid+1,r,pos,v);
    	return p;
    }
    int query(int x,int y,int L,int R,int l,int r){
    	if(L>=l&&R<=r)return tr[y].sum-tr[x].sum;
    	int mid=(L+R)>>1,res=0;
    	if(l<=mid)res=query(tr[x].ls,tr[y].ls,L,mid,l,r);
    	if(mid<r)res+=query(tr[x].rs,tr[y].rs,mid+1,R,l,r);
    	return res;
    }
    int main(){
    	n=read();m=read();
    	for(int i=1;i<=n;++i)a[i]=read();
    	for(int i=1;i<=n;++i)rt[i]=change(rt[i-1],0,M,a[i],1);
    	for(int i=1;i<=m;++i){
    		int b=read(),x=read(),l=read(),r=read();
    		int ans=0;
    		for(int j=23;j>=0;--j){
    			int L=0,R=M,flag;
    			if((b>>j)&1)L=ans,R=ans+(1<<j)-1,flag=0;
    			else L=ans+(1<<j),R=ans+(1<<(j+1))-1,flag=1;
    			L-=x;R-=x;
    			L=Max(L,0);R=Min(R,M);
    			if(!query(rt[l-1],rt[r],0,M,L,R))flag^=1;//the direction of node
    			ans+=(flag<<j);
    		}
    		printf("%d
    ",ans^b);
    	}
    	return 0;
    }
    
  • 相关阅读:
    CSS BEM 命名规范简介
    React 端的编程范式
    在React应用程序中用RegEx测试密码强度
    React 中获取数据的 3 种方法及它们的优缺点
    vue props传值常见问题
    如何理解vue中的v-model?
    利用jQuery not()方法选取除某个元素外的所有元素
    初识Nest.js
    react-绑定this并传参的三种方式
    Angular怎么防御xss攻击?
  • 原文地址:https://www.cnblogs.com/h-lka/p/14965957.html
Copyright © 2020-2023  润新知