20200725 T3 sort【区间异或,区间排序,平衡树 + trie】

题目描述

长度为 n n n 的序列, 0 ≤ a i < 2 32 0\le a_i<2^{32} 0ai<232
要求支持 区间与,区间或,区间异或,区间排序。
输出最终的 a a a 序列。
n , m ≤ 1 0 5 n,m\le10^5 n,m105

题目分析

a i < 16 a_i<16 ai<16 的时候可以线段树维护每种数的个数,排序的时候提取每种数然后区间赋值。看似是 l o g 3 log^3 log3 实际上却跑得很快,(可能有些数没有;赋值时的pushup可以小常数memset)

正解:

平衡树维护序列,01trie 维护已经排好序的权值递增段。

排序时用平衡树找到这段区间,在边角需要 trie 分裂

然后将这段区间对应的所有 trie 合并。合并前先下放标记,保证有序。

标记可能是把某些位强制变0/1,翻转某些位,对应的操作是左右儿子跑到一边/交换左右儿子,前者做一次 trie 合并。(下放标记和合并嵌套了诶!)

将合并完的 trie 加入平衡树。

分裂 trie 时平衡树的标记不打到 trie 上,因为在序列中的位置没有变,但是 trie 内部的标记要下放,是排序没排完的。

修改同样分裂出这段区间,然后在平衡树上打标记。在排序时把平衡树上的标记打到 trie 上,修改时不打在 trie 上。

平衡树点上只需要存懒标记、缓存的准备打在trie上的标记、 trie 的根、子树大小。

trie 只需要存懒标记,子树大小。

这个标记下放有点难搞。。。我存了3个标记,强制赋0的位,强制赋1的位,翻转的位,二进制表示。

先用0/1标记强制修改,再看翻转标记对应儿子的强制修改标记,剩下的翻转位与儿子的翻转标记异或。

trie 合并的复杂度是 O ( 删 除 节 点 个 数 ) O(删除节点个数) O() ,每次分裂增加 O ( log ⁡ ) O(\log) O(log) 个点。所以总复杂度还是 O ( ( n + m ) ( log ⁡ V + log ⁡ n ) ) O((n+m)(\log V+\log n)) O((n+m)(logV+logn))

OI生涯第二长的代码。。调出无数锅。。

  • 注意 trie 树分裂和输出答案的时候到最底层可能不止一个点。
  • Treap分裂的时候注意标记也要复制。
  • 新建Treap节点的时候 siz 是对应 trie 树的大小而不是 1
  • 最后输出答案的时候平衡树上的标记不是打到 trie 上,那样就是排序了,应该对最底层的值施加这个标记。
  • trie 分裂近乎稳稳的 32 32 32 层,如果不写空间回收的话数组要开到 3*log(初始一个log,Treap分裂两次)

Code:

#include<bits/stdc++.h>
#define maxn 100005
#define maxp maxn*105
using namespace std;
char cb[1<<20],*cs,*ct;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<20,stdin),cs==ct)?0:*cs++)
template<class T>void read(T &a){
	char c;while(!isdigit(c=getc()));
	for(a=c-'0';isdigit(c=getc());a=a*10+c-'0');
}
typedef unsigned int ui;
int n,m;
ui a[maxn];
struct tag{
	ui x[2],rev;
	tag(ui a=0,ui b=0,ui c=0){x[0]=a,x[1]=b,rev=c;}
	bool empty(){return !x[0]&&!x[1]&&!rev;}
	void operator += (const tag &t){
		for(int i=0;i<2;i++){
			ui v=t.x[i];
			x[i]|=v, x[!i]&=~v, rev&=~v;
		}
		ui v=(x[0]&t.rev)|(x[1]&t.rev);
		x[0]^=v,x[1]^=v;
		rev^=t.rev^v;
	}
	void init(ui &v){
		v&=~x[0], v|=x[1], v^=rev;
	}
}treap[maxn],trie[maxp],tg[maxp];

int ch[maxp][2],cnt[maxp],tot;
void ins(int &rt,ui x){
	if(!rt) rt=++tot;
	int r=rt,v;
	for(int i=31;i>=0;r=ch[r][v],i--){
		cnt[r]++;
		if(!ch[r][v=x>>i&1]) ch[r][v]=++tot;
	}
	cnt[r]++;
}
void merge_trie(int&,int,int,int);
void down_trie(int i,int d){
	if(d<0||tg[i].empty()) return;
	if(tg[i].x[0]>>d&1) merge_trie(ch[i][0],ch[i][0],ch[i][1],d-1),ch[i][1]=0;
	else if(tg[i].x[1]>>d&1) merge_trie(ch[i][1],ch[i][1],ch[i][0],d-1),ch[i][0]=0;
	else if(tg[i].rev>>d&1) swap(ch[i][0],ch[i][1]);
	if(ch[i][0]) tg[ch[i][0]]+=tg[i];
	if(ch[i][1]) tg[ch[i][1]]+=tg[i];
	tg[i]=tag();
}
void merge_trie(int &t,int x,int y,int d){
	if(!x||!y) return void(t=x+y);
	down_trie(x,d),down_trie(y,d);
	cnt[t=x]+=cnt[y];
	merge_trie(ch[t][0],ch[x][0],ch[y][0],d-1),merge_trie(ch[t][1],ch[x][1],ch[y][1],d-1);
}
void split_trie(int x,int &y,int k,int d){
	y=++tot;
	if(d==-1) {cnt[y]=cnt[x]-k,cnt[x]=k; return;}
	down_trie(x,d); int sz=cnt[ch[x][0]];
	if(k>sz) split_trie(ch[x][1],ch[y][1],k-sz,d-1);
	else swap(ch[x][1],ch[y][1]);
	if(k<sz) split_trie(ch[x][0],ch[y][0],k,d-1);
	cnt[y]=cnt[x]-k,cnt[x]=k;
}

int root,lc[maxn],rc[maxn],siz[maxn],rnd[maxn],rt[maxn],rec[maxn],tmprt;
int Newtreap(int r){
	int i=rec[(*rec)--]; 
	return siz[i]=cnt[r],rnd[i]=rand(),rt[i]=r,i;//attention lc,rc,tag.
}
void upd_treap(int i){siz[i]=siz[lc[i]]+siz[rc[i]]+cnt[rt[i]];}
void down_treap(int i){
	if(treap[i].empty()) return;
	if(lc[i]) treap[lc[i]]+=treap[i],trie[lc[i]]+=treap[i];
	if(rc[i]) treap[rc[i]]+=treap[i],trie[rc[i]]+=treap[i];
	treap[i]=tag();
}
void merge(int &t,int a,int b){
	if(!a||!b) return void(t=a+b);
	if(rnd[a]<rnd[b]) down_treap(t=a),merge(rc[t],rc[a],b);
	else down_treap(t=b),merge(lc[t],a,lc[b]);
	upd_treap(t);
}
void split(int t,int &a,int &b,int k){
	if(!t) return void(a=b=0);
	down_treap(t);
	if(k<=siz[lc[t]]) b=t,split(lc[t],a,lc[b],k);
	else if(k>=siz[lc[t]]+cnt[rt[t]]) a=t,split(rc[t],rc[a],b,k-siz[lc[t]]-cnt[rt[t]]);
	else{
		split_trie(rt[t],tmprt,k-siz[lc[t]],31);
		a=t, b=Newtreap(tmprt),rc[b]=rc[t],rc[t]=0,upd_treap(b);
		trie[b]=trie[t]; //!!!
	}
	upd_treap(t);
}
void dfs(int &i){
	if(!i) return;
	down_treap(i),tg[rt[i]]+=trie[i],trie[i]=tag();
	merge_trie(tmprt,tmprt,rt[i],31),rt[i]=0;
	dfs(lc[i]),dfs(rc[i]),rec[++*rec]=i,i=0;
}
ui ans[maxn];
void final(int i,ui x,int d,tag offset){
	if(d==-1) {offset.init(x); while(cnt[i]--) ans[++*ans]=x; return;}
	down_trie(i,d);
	if(ch[i][0]) final(ch[i][0],x,d-1,offset);//cnt[ch[i][0]]?
	if(ch[i][1]) final(ch[i][1],x|1u<<d,d-1,offset);
}
void final(int i){
	if(!i) return;
	down_treap(i);
	final(lc[i]),final(rt[i],0,31,trie[i]),final(rc[i]);
}
int main()
{
	freopen("sort.in","r",stdin);
	freopen("sort.out","w",stdout);
	read(n),read(m);
	for(int i=1;i<=n;i++) rec[++*rec]=n-i+1;
	for(int i=1,x;i<=n;i++) read(x),ins(tmprt=0,x),merge(root,root,Newtreap(tmprt));
	ui v;
	for(int op,l,r,L,M,R;m--;){
		read(op),read(l),read(r),op!=4&&(read(v),0);
		split(root,L,R,r),split(L,L,M,l-1);
		if(op<=3){
			if(op==1) treap[M]+=tag(0,v,0),trie[M]+=tag(0,v,0);
			if(op==2) treap[M]+=tag(~v,0,0),trie[M]+=tag(~v,0,0);
			if(op==3) treap[M]+=tag(0,0,v),trie[M]+=tag(0,0,v);
			merge(L,L,M),merge(root,L,R);
		}
		if(op==4){
			tmprt=0,dfs(M);
			merge(L,L,Newtreap(tmprt)),merge(root,L,R);
		}
		//cerr<<tot<<endl;
	}
	final(root);
	for(int i=1;i<=n;i++) printf("%u%c",ans[i],i==n?10:32);
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在现有省、市港口信息化系统进行有效整合基础上,借鉴新 一代的感知-传输-应用技术体系,实现对码头、船舶、货物、重 大危险源、危险货物装卸过程、航管航运等管理要素的全面感知、 有效传输和按需定制服务,为行政管理人员和相关单位及人员提 供高效的管理辅助,并为公众提供便捷、实时的水运信息服务。 建立信息整合、交换和共享机制,建立健全信息化管理支撑 体系,以及相关标准规范和安全保障体系;按照“绿色循环低碳” 交通的要求,搭建高效、弹性、高可扩展性的基于虚拟技术的信 息基础设施,支撑信息平台低成本运行,实现电子政务建设和服务模式的转变。 实现以感知港口、感知船舶、感知货物为手段,以港航智能 分析、科学决策、高效服务为目的和核心理念,构建“智慧港口”的发展体系。 结合“智慧港口”相关业务工作特点及信息化现状的实际情况,本项目具体建设目标为: 一张图(即GIS 地理信息服务平台) 在建设岸线、港口、港区、码头、泊位等港口主要基础资源图层上,建设GIS 地理信息服务平台,在此基础上依次接入和叠加规划建设、经营、安全、航管等相关业务应用专题数据,并叠 加动态数据,如 AIS/GPS/移动平台数据,逐步建成航运管理处 "一张图"。系统支持扩展框架,方便未来更多应用资源的逐步整合。 现场执法监管系统 基于港口(航管)执法基地建设规划,依托统一的执法区域 管理和数字化监控平台,通过加强对辖区内的监控,结合移动平 台,形成完整的多维路径和信息追踪,真正做到问题能发现、事态能控制、突发问题能解决。 运行监测和辅助决策系统 对区域港口与航运业务日常所需填报及监测的数据经过科 学归纳及分析,采用统一平台,消除重复的填报数据,进行企业 输入和自动录入,并进行系统智能判断,避免填入错误的数据, 输入的数据经过智能组合,自动生成各业务部门所需的数据报 表,包括字段、格式,都可以根据需要进行定制,同时满足扩展 性需要,当有新的业务监测数据表需要产生时,系统将分析新的 需求,将所需字段融合进入日常监测和决策辅助平台的统一平台中,并生成新的所需业务数据监测及决策表。 综合指挥调度系统 建设以港航应急指挥中心为枢纽,以各级管理部门和经营港 口企业为节点,快速调度、信息共享的通信网络,满足应急处置中所需要的信息采集、指挥调度和过程监控等通信保障任务。 设计思路 根据项目的建设目标和“智慧港口”信息化平台的总体框架、 设计思路、建设内容及保障措施,围绕业务协同、信息共享,充 分考虑各航运(港政)管理处内部管理的需求,平台采用“全面 整合、重点补充、突出共享、逐步完善”策略,加强重点区域或 运输通道交通基础设施、运载装备、运行环境的监测监控,完善 运行协调、应急处置通信手段,促进跨区域、跨部门信息共享和业务协同。 以“统筹协调、综合监管”为目标,以提供综合、动态、实 时、准确、实用的安全畅通和应急数据共享为核心,围绕“保畅通、抓安全、促应急"等实际需求来建设智慧港口信息化平台。 系统充分整合和利用航运管理处现有相关信息资源,以地理 信息技术、网络视频技术、互联网技术、移动通信技术、云计算 技术为支撑,结合航运管理处专网与行业数据交换平台,构建航 运管理处与各部门之间智慧、畅通、安全、高效、绿色低碳的智 慧港口信息化平台。 系统充分考虑航运管理处安全法规及安全职责今后的变化 与发展趋势,应用目前主流的、成熟的应用技术,内联外引,优势互补,使系统建设具备良好的开放性、扩展性、可维护性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值