zoukankan      html  css  js  c++  java
  • 【XSY1098】第k小 可持久化trie

    题目描述

      给你一个长度为(n)数列(a),有(m)次操作:

       (1~x):把所有数异或(x)

       (2~x):把所有数与(x)

       (3~x):把所有数或(x)

       (4~l~r~k):求(a_lldots a_r)的第(k)小值。

      (n,mleq 50000,0leq x,a_i<2^{31})

    题解

      如果只有查询操作,可以用可持久化trie解决。

      加上亦或操作,可以打标记解决。

      与操作和或操作每次会将所有数的某些二进制变成一样,这些二进制位将来都是一样的。

      所以直接暴力执行操作,然后打标记,表示这些二进制位已经相同了。如果与操作或或操作的(x)修改的二进制位都已经相同,就直接跳过。

      时间复杂度:(O(mlog x+nlog^2x))

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<ctime>
    #include<utility>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> pii;
    int c[20000010][2];
    int s[20000010];
    int rt[50010];
    int cnt;
    int xo;
    int insert(int x,int v,int d)
    {
    	int y=++cnt;
    	s[y]=s[x]+1;
    	c[y][0]=c[x][0];
    	c[y][1]=c[x][1];
    	if(d==-1)
    		return y;
    	int b=(v>>d)&1;
    	c[y][b]=insert(c[y][b],v,d-1);
    	return y;
    }
    int query(int x,int y,int k,int d)
    {
    	if(d==-1)
    		return 0;
    	int b=(xo>>d)&1;
    	if(s[c[y][b]]-s[c[x][b]]>=k)
    		return query(c[x][b],c[y][b],k,d-1);
    	return query(c[x][b^1],c[y][b^1],k-s[c[y][b]]+s[c[x][b]],d-1)|(1<<d);
    }
    int a[50010];
    int n,m;
    int all=0xffffffff,now=0;
    void build()
    {
    	int i;
    	cnt=0;
    	rt[0]=0;
    	for(i=1;i<=n;i++)
    		rt[i]=insert(rt[i-1],a[i],31);
    }
    int main()
    {
    	freopen("xsy1098.in","r",stdin);
    	freopen("xsy1098.out","w",stdout);
    	int i,j;
    	scanf("%d%d",&n,&m);
    	for(i=1;i<=n;i++)
    		scanf("%d",&a[i]);
    	build();
    	char op[5];
    	int x,y,k;
    	for(i=1;i<=m;i++)
    	{
    		scanf("%s",op);
    		if(op[0]=='X')
    		{
    			scanf("%d",&x);
    			xo^=x;
    			xo&=all;
    			now^=x&(~all);
    		}
    		else if(op[0]=='O')
    		{
    			scanf("%d",&x);
    			if(x&all)
    			{
    				all&=~x;
    				for(j=1;j<=n;j++)
    					a[j]&=all;
    				build();
    			}
    			now|=x&(~all);
    			xo&=all;
    		}
    		else if(op[1]=='n')
    		{
    			scanf("%d",&x);
    			if((~x)&all)
    			{
    				all&=x;
    				for(j=1;j<=n;j++)
    					a[j]&=all;
    				build();
    			}
    			now&=x&(~all);
    			xo&=all;
    		}
    		else
    		{
    			scanf("%d%d%d",&x,&y,&k);
    			int ans=query(rt[x-1],rt[y],k,31);
    			ans|=now;
    			printf("%d
    ",ans);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    linux-磁盘挂载脚本
    VSCode插件
    数据模拟--Mock.js
    Vue学习笔记之组件
    Vue学习笔记之动画
    Echarts柱状图常用配置项
    Vue学习笔记之总体结构
    JSON数据格式开发规范
    苹果电脑和手机浏览器的区分
    二维码生成插件(jquery.qrcode.js)说明文档
  • 原文地址:https://www.cnblogs.com/ywwyww/p/8513120.html
Copyright © 2011-2022 走看看