1. 程式人生 > >BZOJ 4184 shallot 分治+高斯消元

BZOJ 4184 shallot 分治+高斯消元

題目大意:給定一個可重集合,每個時刻加入一個數或刪除一個數,每次操作後詢問子集的最大異或和

每個數存在的時間都是一些區間
按照時間分治,維護線性基,時間複雜度O(nlognlogai)
然而資料範圍是50W,出題人在想什麼。。。。

#include <map>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 500500
using namespace std
; struct Linear_Base{ int a[31]; Linear_Base() {} Linear_Base(bool) { memset(a,0,sizeof a); } void Insert(int x) { int i; for(i=30;~i;i--) if(x&(1<<i)) { if(a[i]) x^=a[i]; else
{ a[i]=x;break; } } } int Query() { int i,re=0; for(i=30;~i;i--) re=max(re,re^a[i]); return re; } }; int n; map<int,int> cnt,last_pos; void Divide_And_Conquer(int x,int y,Linear_Base lb,vector
<pair<pair<int,int>
,int> > a) { int i,mid=x+y>>1; vector<pair<pair<int,int>,int> > l,r; for(i=0;i<(signed)a.size();i++) { if(a[i].first.first==x&&a[i].first.second==y) lb.Insert(a[i].second); else if(a[i].first.second<=mid) l.push_back(a[i]); else if(a[i].first.first>mid) r.push_back(a[i]); else l.push_back(make_pair(make_pair(a[i].first.first,mid),a[i].second)), r.push_back(make_pair(make_pair(mid+1,a[i].first.second),a[i].second)); } if(x==y) printf("%d\n",lb.Query()); else Divide_And_Conquer(x,mid,lb,l),Divide_And_Conquer(mid+1,y,lb,r); } int main() { int i,x; vector<pair<pair<int,int>,int> > a; cin>>n; for(i=1;i<=n;i++) { scanf("%d",&x); if(x>0) { if(++cnt[x]==1) last_pos[x]=i; } else { if(--cnt[-x]==0) a.push_back(make_pair(make_pair(last_pos[-x],i-1),-x)); } } for(map<int,int>::iterator it=cnt.begin();it!=cnt.end();it++) if(it->second) a.push_back(make_pair(make_pair(last_pos[it->first],n),it->first)); Divide_And_Conquer(1,n,Linear_Base(false),a); return 0; }