zoukankan      html  css  js  c++  java
  • P4585[FJOI2015]火星商店问题【线段树,可持久化Trie】

    正题

    题目链接:https://www.luogu.com.cn/problem/P4585


    题目大意

    \(n\)个集合,开始每个集合中有一个数字。

    1. 开启新的一天并且往集合\(s\)中插入数字\(v\)
    2. 询问\(d\)天以内插入的数字(包括最开始的)中\(l\sim r\)集合内的数字异或上\(x\)的最大值。

    所有数字均在\([0,10^5]\)范围内


    解题思路

    线段树上每个节点维护一个可持久化\(Trie\)

    每次插入就把包含\(s\)的节点插入数字\(v\)

    询问就正常查询即可。

    时空间复杂度都是\(O(n\log^2 n)\)

    好像还有空间是\(O(n\log n)\)的线段树分治算法,不过懒得写了。


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=1e5+10;
    int n,m,cnt,p[N],rt[N<<2];
    int ch[N<<9][2],last[N<<9];
    int Insert(int x,int val,int id,int k=16){
    	int y=++cnt;
    	if(k<0){last[y]=id;return y;}
    	int c=(val>>k)&1;
    	ch[y][c^1]=ch[x][c^1];
    	ch[y][c]=Insert(ch[x][c],val,id,k-1);
    	last[y]=max(last[ch[y][0]],last[ch[y][1]]);
    	return y;
    }
    int Ask(int x,int val,int lim,int k=16){
    	if(k<0)return val;
    	int c=(val>>k)&1;
    	if(last[ch[x][c^1]]>=lim)
    		return Ask(ch[x][c^1],val|(1<<k),lim,k-1);
    	if(last[ch[x][c]]>=lim)
    		return Ask(ch[x][c],val^(val&(1<<k)),lim,k-1);
    	return 0;
    }
    void Change(int x,int l,int r,int pos,int id,int val){
    	rt[x]=Insert(rt[x],val,id);
    	if(l==r)return;int mid=(l+r)>>1;
    	if(pos<=mid)Change(x*2,l,mid,pos,id,val);
    	else Change(x*2+1,mid+1,r,pos,id,val);
    	return;
    }
    int Query(int x,int L,int R,int l,int r,int val,int lim){
    	if(L==l&&R==r)return Ask(rt[x],val,lim);
    	int mid=(L+R)>>1;
    	if(r<=mid)return Query(x*2,L,mid,l,r,val,lim);
    	if(l>mid)return Query(x*2+1,mid+1,R,l,r,val,lim);
    	return max(Query(x*2,L,mid,l,mid,val,lim),Query(x*2+1,mid+1,R,mid+1,r,val,lim));
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++){
    		int x;scanf("%d",&x);
    		p[i]=Insert(p[i-1],x,i);
    	}
    	int id=0;
    	for(int i=1;i<=m;i++){
    		int op;scanf("%d",&op);
    		if(op){
    			int l,r,x,d,ans=0;
    			scanf("%d%d%d%d",&l,&r,&x,&d);
    			ans=Query(1,1,n,l,r,x,id-d+1);
    			ans=max(ans,Ask(p[r],x,l));
    			printf("%d\n",ans);
    		}
    		else{
    			int s,v;
    			scanf("%d%d",&s,&v);id++;
    			Change(1,1,n,s,id,v);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    搭建DHCP服务
    sshd免密登陆
    加密类型以及数据加密解密过程
    搭建私有CA并实现证书颁发
    CentOS 7 启动流程
    Linux命令:tcpdump命令
    Linux命令:ping命令
    Linux命令:ss命令
    Linux命令:ip命令
    Linux命令:netstat命令
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/14404375.html
Copyright © 2011-2022 走看看