• 【BZOJ-4184 】 Shallot 线段树按时间分治 + 线性基


    4184: shallot

    Time Limit: 30 Sec  Memory Limit: 128 MB
    Submit: 356  Solved: 180
    [Submit][Status][Discuss]

    Description

    小苗去市场上买了一捆小葱苗,她突然一时兴起,于是她在每颗小葱苗上写上一个数字,然后把小葱叫过来玩游戏。

    每个时刻她会给小葱一颗小葱苗或者是从小葱手里拿走一颗小葱苗,并且让小葱从自己手中的小葱苗里选出一些小葱苗使得选出的小葱苗上的数字的异或和最大。
    这种小问题对于小葱来说当然不在话下,但是他的身边没有电脑,于是他打电话给同为Oi选手的你,你能帮帮他吗?
    你只需要输出最大的异或和即可,若小葱手中没有小葱苗则输出0。

    Input

    第一行一个正整数n表示总时间;第二行n个整数a1,a2...an,若ai大于0代表给了小葱一颗数字为ai的小葱苗,否则代表从小葱手中拿走一颗数字为-ai的小葱苗。

    Output

    输出共n行,每行一个整数代表第i个时刻的最大异或和。

    Sample Input

    6
    1 2 3 4 -2 -3

    Sample Output

    1
    3
    3
    7
    7
    5

    HINT

     N<=500000,Ai<=2^31-1

    Source

    Solution

    新姿势,线段树对时间分治。
    询问可以直接利用线性基贪心求解,问题在于线性基不支持删除操作。

    考虑对时间分治,就是按时间建线段树,对于一个数,得到他的存在时间区间$[l,r]$,然后对线段树上相应节点记录这个数。

    最后DFS线段树,在叶子节点求解。

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<map>
    using namespace std;
    inline int read()
    {
    	int x=0,f=1; char ch=getchar();
    	while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    	while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    	return x*f;
    }
    
    #define MAXN 500010
    
    int N;
    
    struct SgtNode{
    	int l,r; vector<int>a;
    }tree[MAXN<<2];
    
    struct LNode{
    	int a[31];
    	LNode() {memset(a,0,sizeof(a));}
    	int& operator [] (const int i) {
    		return a[i];
    	}
    }la;
    
    inline void Insert(LNode &la,int x)
    {
    	for (int i=30; i>=0; i--) {
    		if ((x>>i)&1) {
    			if (!la[i]) {la[i]=x; break;}
    				else x^=la[i];
    		}
    	}
    }
    
    map<int,int>tim;
    
    inline void Build(int now,int l,int r)
    {
    	tree[now].l=l; tree[now].r=r; tree[now].a.clear();
    	if (l==r) return;
    	int mid=(l+r)>>1;
    	Build(now<<1,l,mid); Build(now<<1|1,mid+1,r);
    }
    
    inline void Update(int now,int L,int R,int val)
    {
    	int l=tree[now].l,r=tree[now].r;
    	if (L<=l && R>=r) {
    		tree[now].a.push_back(val);
    		return;
    	}
    	int mid=(l+r)>>1;
    	if (L<=mid) Update(now<<1,L,R,val);
    	if (R>mid) Update(now<<1|1,L,R,val);
    }
    
    inline void Query(int now,LNode LA)
    {
    	int l=tree[now].l,r=tree[now].r;
    	for (int i=0; i<tree[now].a.size(); i++)
    		Insert(LA,tree[now].a[i]);
    	if (l==r) {
    		int ans=0;
    		for (int i=30; i>=0; i--) 
    			if ((ans^LA[i])>ans) ans^=LA[i];
    		printf("%d
    ",ans);
    		return; 
    	}
    	Query(now<<1,LA); Query(now<<1|1,LA); 
    }
    
    
    int main()
    {
    	N=read();
    	
    	int st=((1LL<<31)-1);
    	for (int i=1; i<=N; i++) {
    		int x=read(); tim[x]=i;
    		if (x>0) st=min(st,x);
    	}
    	
    	Build(1,1,N);
    	
    	for (map<int,int>::iterator i=tim.find(st); i!=tim.end(); i++) {
    		int x=i->first,tl=i->second,tr=tim[-x] ? (tim[-x]-1):N;
    		Update(1,tl,tr,x);
    //		printf("%d  %d  %d
    ",x,tl,tr);
    	}
    	
    	Query(1,la);
    	
    	return 0;
    }
    
    /*
    6
    1 2 3 4 -2 -3
    */
    

      

  • 相关阅读:
    log4net
    winform datagridview 刷新数据不需要重新绑定
    Git 简明教程(一)
    Task详解【转载】
    虚拟机Linux系统手动指定IP
    DataGrip连接sqlserver,提示驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接的解决方法
    c#中Equals方法和GetHashCode
    获取程序集的类型信息
    第一个windows桌面应用程序
    在运行时让PropertyGrid动态显示我们想要的对象属性
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/6612729.html
Copyright © 2020-2023  润新知