zoukankan      html  css  js  c++  java
  • P4585 [FJOI2015]火星商店问题

    P4585 [FJOI2015]火星商店问题

    线段树+可持久化01Trie。

    首先区间的限制很容易想到线段树,然后异或最大值很明显就是可持久化 01 Trie,于是可以维护,至于 d 天内的限制,我们插入 01Trie 的时候打一个时间 (tag) ,询问的时候看一下满不满足就行了。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    template <typename T>
    inline void read(T &x){
    	x=0;char ch=getchar();bool f=false;
    	while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();}
    	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    	x=f?-x:x;
    	return ;
    }
    template <typename T>
    inline void write(T x){
    	if(x<0) putchar('-'),x=-x;
    	if(x>9) write(x/10);
    	putchar(x%10^48);
    	return ;
    }
    const int N=1e5+5,M=5e7+5,INF=0x3f3f3f3f;
    int n,m,d,cnt,a[N];
    int tr[M][2],tag[M][2],root[N<<2];
    struct SegMentTree{
    	int l,r;
    	#define l(x) tree[x].l
    	#define r(x) tree[x].r
    }tree[N<<2];
    void Insert(int p,int val,int t){
    	for(int i=1<<18;i;i>>=1){
    		bool ch=val&i;
    		if(!tr[p][ch])tr[p][ch]=++cnt;
    		tag[p][ch]=max(t,tag[p][ch]);
    		p=tr[p][ch];
    	}
    	return ;
    }
    int Ask(int p,int val,int t){
    	int res=0;
    	for(int i=1<<18;i;i>>=1){
    		bool ch=val&i;
    		if(tr[p][ch^1]&&tag[p][ch^1]>=t)res|=i,p=tr[p][ch^1];
    		else if(tr[p][ch]&&tag[p][ch]>=t)p=tr[p][ch];
    	}
    	return res;
    }
    void Build(int x,int l,int r){
    	l(x)=l,r(x)=r;
    	root[x]=++cnt;
    	for(int i=l;i<=r;i++) Insert(root[x],a[i],INF);
    	if(l==r)return;
    	int mid=(l+r)>>1;
    	Build(x<<1,l,mid);
    	Build(x<<1|1,mid+1,r);
    	return ;
    }
    void Modify(int x,int pos,int val,int t){
    	int l=l(x),r=r(x);
    	Insert(root[x],val,t);
    	if(l==r)return;
    	int mid=(l+r)>>1;
    	if(pos<=mid) Modify(x<<1,pos,val,t);
    	else Modify(x<<1|1,pos,val,t);
    	return ;
    }
    int Query(int x,int L,int R,int val,int t){
    	int l=l(x),r=r(x);
    	if(L<=l&&r<=R)return Ask(root[x],val,t);
    	int mid=(l+r)>>1,res=0;
    	if(L<=mid) res=max(res,Query(x<<1,L,R,val,t));
    	if(R>mid) res=max(res,Query(x<<1|1,L,R,val,t));
    	return res;
    }
    int main(){
    	read(n),read(m);
    	for(int i=1;i<=n;i++) read(a[i]);
    	Build(1,1,n);
    	while(m--){
    		int op;
    		read(op);
    		if(!op){
    			int pos,val;d++;
    			read(pos),read(val);
    			Modify(1,pos,val,d);
    		}
    		else{
    			int l,r,x,t;
    			read(l),read(r),read(x),read(t);
    			write(Query(1,l,r,x,d-t+1)),puts("");
    		}
    	}
    	return 0;
    }
    

    这道题也可以线段树分治+可持久化 01 Trie,我们发现每一个商品对于询问有一个生效区间,于是线段树分治。

    好像还有 CDQ分治 的神奇做法。

  • 相关阅读:
    list切片
    class面向对象编程学习笔记
    斐波那契数
    module学习笔记
    Python基础
    产品经理培训行业---以起点学院为主体的相关竞品分析报告
    基础数据结构-二叉树-赫夫曼树的构建与编码
    大众点评APP分析随笔
    滴滴拼车功能分析
    梅沙教育APP简单分析-版本:iOS v1.2.21-Nathaneko-佳钦
  • 原文地址:https://www.cnblogs.com/Akmaey/p/14690219.html
Copyright © 2011-2022 走看看