LOJ2312 LUOGU-P3733「HAOI2017」八纵八横 (异或线性基、生成树、线段树分治)
八纵八横
题目描述
Anihc国有n个城市,这n个城市从1~n编号,1号城市为首都。城市间初始时有m条高速公路,每条高速公路都有一个非负整数的经济影响因子,每条高速公路的两端都是城市(可能两端是同一个城市),保证任意两个城市都可以通过高速公路互达。
国正在筹划“八纵八横”的高铁建设计划,计划要修建一些高速铁路,每条高速铁路两端也都是城市(可能两端是同一个城市),也都有一个非负整数的经济影响因子。国家还计划在“八纵八横”计划建成之后,将“一带一路”扩展为“一带_路一环”,增加“内陆城市经济环”即选择一条从首都出发沿若一系列高铁与高速公路走的路径,每条高铁或高速公路可以经过多次,每座城市也可以经过多次,最后路径又在首都结束。令“内陆城市经济环”的GDP为依次将这条路径上所经过的高铁或高速公路的经济影响因子异或起来(一条路经过多次则会被计算多次)。
现在Anihc在会议上讨论“八纵八横”的建设计划方案,他们会不断地修改计划方案,希望你能实时反馈对于当前的“八纵八横”的建设计划的方案“内陆城市经济环”的最大是多少。
初始时,八纵八横1计划中不包含任何—条高铁,有以下3种操作
- Add x y z
在计划中给在城市x和城市y之间建设一条高铁,其经济影响因子为z,如果这是第k个Add操作,则将这条高铁命名为k号高铁
- Cancel k
将计划中的k号高铁取消掉,保证此时k号高铁一定存在
- Change k z
表示将第k号高铁的经济影响因子更改为z,保证此时k号高铁一定存在
输入格式
第一行3个整数n,m,P,表示城市个数.高速公路条数.操作个数
接下来m行.每行3个整数表示高速公路的信息。
接下来P行.每行为一个操作
注意:输入的所有经济影响因子都将以二进制的形式从高位到低位给出。
输出格式
第一行一个整数.表示如果不修建任何高铁,“内陆城市经济环”的GDP最大值
接下Q行.每行一个整数.表示进行了对应的每一个操作之后.对于当前的计划.“内 陆城市经济环”的CDP最大值。
注意:输出的答案也要以二进制的形式从高位到低位给出。
输入输出样例
输入 #1
4 4 3
1 2 1110
1 3 10
2 4 1110
2 3 100
Add 3 4 11
Change 1 101
Cancel 1输出 #1
1000
1001
1111
1000说明/提示
【数据规模与约定】
令所有的经济因子二进制表示的最多位数为len.数据满足以下表格

对于所有的数据保证:n,m<=500,Q,len<=1000,1<x,y<n.且Add操作不超过500个.两个城市之间可能有多条高速公路或高铁,高速公路或高铁的两端可能是同一个城市(即 有重边.有自环)。
题解
注意题意,它原先就有一个连通无向图,后来附加了一些边。
由于它是无向图,且每条边可以走多次,所以他的最大权值环的权值就是图中任选一些环权值异或起来的最大值,这应该很好理解,因为考虑走到一个环和走回去,来和去的路径权值异或起来为零,没有影响,所以如果当前异或一个图中的环权值可以更大的话,那么走一遍这个环后肯定是更优的(但是并不代表这题是贪心,听我讲)。
所以我们可以考虑用线性基。
把环的权值都放进线性基里,最后算出答案。
注意,并不是要把所有可以形成的环都放进去,由于线性基的性质,只需要保证放进去的所有环组成的子图内包含了原图的所有环就可以了,举个例子,假设这么一张图:

那么我们只需要放入“A-B-C-D”、“A-B-D”、“B-C-D”三个环中的任意两个。
由于它放入的边要改权值,并且要删边,线性基不支持删边,所以(观察数据发现)我们可以用线段树分治,这样就可以把删边、改权值全都变成加边操作,只是多了个2的常数(吧?
要维护每次加边后增加的环,看似有点麻烦,但是我们可以证明每加一次边最多只会在线性基里多加一个环,而且由于原本就是一个连通图,所以可以随便建一个生成树,然后把多余的边(每条可以对应一个环!)计算对应的环——即两端点连向lca的环的权值插入线性基,Add操作加的边也是一个道理。
最后由于它的二进制数有1000位,我们必须用bitset来打线性基,其中需要一些卡空间的技巧。
WARNING:要特判P=0的情况
CODE
#include<cstdio>
#include<cstring>
#include<vector>
#include<stack>
#include<queue>
#include<algorithm>
#include<map>
#include<cmath>
#include<bitset>
#include<iostream>
#define MAXN 7005
#define LL long long
#define ULL unsigned LL
#define rg register
#define lowbit(x) (-(x) & (x))
#define ENDL putchar('\n')
#define DB double
#define bs bitset<1005>
#pragma GCC optimize(2)
//#pragma G++ optimize(3)
//#define int LL
using namespace std;
inline int read() {
	int f = 1,x = 0;char s = getchar();
	while(s < '0' || s > '9') {if(s == '-') f = -1;s = getchar();}
	while(s >= '0' && s <= '9') {x = x * 10 - '0' + s;s = getchar();}
	return x * f;
}
struct it{
	int v,id;
	it(){id = v = 0;}
	it(int V,int I){v = V;id = I;}
};
int n,m,i,j,s,o,k;
bs w0[MAXN],w[MAXN],sum[MAXN];
int u[MAXN],v[MAXN],tm[MAXN];
vector<it> g[MAXN];
int f[MAXN],d[MAXN],fe[MAXN];
bool vis[MAXN];
bs ans[MAXN],lc[MAXN];
inline int highbit(bs x) {
//	int as = -1;while(x) as ++,x >>= 1;return as;
	int l = 0,r = 1000,mid;
	while(l^r) {
		mid = (l + r) >> 1;
//		printf("1ll<<%d[%lld] <= %d ? %s\n",mid,1ll<<mid,x,(1ll<<mid) <= x ? "Yes!":"No!");
		if((x>>(mid+1)).none()) r=mid;
		else l=mid+1;
	}return l;
}
inline void Cout(bs x) {
	int le = highbit(x);
	for(int i = le;i >= 0;i --) {
		putchar(x.test(i) ? '1':'0');
	}return ;
}
struct XXJ{
	bs F[1202];
	int cnt;
	XXJ(){cnt = 0;}
	inline void ins(bs x) {
		while(x.any()) {
			int j = highbit(x);
			if(F[j].none()) {
				F[j] = x;
				cnt ++;
				return ;
			}
			x ^= F[j];
		}
	}
}xxj[35];
vector<bs> tre[MAXN<<2];
inline void addtree(int a,int l,int r,int al,int ar,bs y) {
	if(al > r || ar < l) return ;
	if(al >= l && ar <= r) {
		tre[a].push_back(y);
		return ;
	}
	int mid = al + ar >> 1;
	addtree(a<<1,l,r,al,mid,y);
	addtree(a<<1|1,l,r,mid+1,ar,y);
	return ;
}
inline void pushdown(int a,int al,int ar,int id) {
	for(int i = 0;i < tre[a].size();i ++) {
		xxj[id].ins(tre[a][i]);
	}
	if(al == ar) {
		bs as;
		for(int i = 1000;i >= 0;i --) {
			if(xxj[id].F[i].any() && !as.test(i)) {
				as = as ^ xxj[id].F[i];
			}
		}
		ans[al] = as;
		return ;
	}
	xxj[id+1] = xxj[id];
	int mid = al + ar >> 1;
	pushdown(a<<1,al,mid,id+1);
	xxj[id+1] = xxj[id];
	pushdown(a<<1|1,mid+1,ar,id+1);
	return ;
}
inline void dfs(int x,int fa,int ie) {
	vis[x] = 1;
	d[x] = d[fa] + 1;
	fe[x] = ie;
	f[x] = fa;
	sum[x] = sum[fa] ^ w0[ie];
	for(int i = 0;i < g[x].size();i ++) {
		if(!vis[g[x][i].v]) {
			dfs(g[x][i].v,x,g[x][i].id);
		}
		else if(g[x][i].v != fa) {
			xxj[0].ins(sum[x] ^ w0[g[x][i].id] ^ sum[g[x][i].v]);
		}
	}
}
signed main() {
	string ss;
	n = read(); m = read(); k = read();
	for(int i = 1;i <= m;i ++) {
		s = read(); o = read();
		cin>>ss;
		bs ww(ss);
		w0[i] = ww;
		g[s].push_back(it(o,i));
		g[o].push_back(it(s,i));
	}
	dfs(1,0,0);
	int kk = 0;
	for(int i = 1;i <= k;i ++) {
		char S[15];
		scanf("%s",S + 1);
		if(S[1] == 'A') {
			kk ++;
			u[kk] = s = read(); v[kk] = o = read();
			cin>>ss;
			lc[kk] = sum[s] ^ sum[o];
			bs ww(ss);
			w[kk] = ww;
			tm[kk] = i;
		}
		else if(S[2] == 'h') {
			s = read();
			cin>>ss;
			bs ww(ss);
			addtree(1,tm[s],i-1,1,k,lc[s] ^ w[s]);
			w[s] = ww;
			tm[s] = i;
		}
		else {
			s = read();
			addtree(1,tm[s],i-1,1,k,lc[s] ^ w[s]);
			tm[s] = 0;
		}
	}
	for(int i = 1;i <= kk;i ++) {
		if(tm[i]) {
			addtree(1,tm[i],k,1,k,lc[i] ^ w[i]);
			tm[i] = 0;
		}
	}
	if(1) {
		bs as;
		for(int i = 1000;i >= 0;i --) {
			if(xxj[0].F[i].any() && !as.test(i)) {
				as = as ^ xxj[0].F[i];
			}
		}
		Cout(as);ENDL;
	}
	if(k < 1) return 0;
	pushdown(1,1,k,0);
	for(int i = 1;i <= k;i ++) {
		Cout(ans[i]);ENDL;
	}
	return 0;
}LOJ2312 LUOGU-P3733「HAOI2017」八纵八横 (异或线性基、生成树、线段树分治)的更多相关文章
- 【Luogu3733】[HAOI2017]八纵八横(线性基,线段树分治)
		[Luogu3733][HAOI2017]八纵八横(线性基,线段树分治) 题面 洛谷 题解 看到求异或最大值显然就是线性基了,所以只需要把所有环给找出来丢进线性基里就行了. 然后线性基不资磁撤销?线段 ... 
- LOJ 2312(洛谷 3733) 「HAOI2017」八纵八横——线段树分治+线性基+bitset
		题目:https://loj.ac/problem/2312 https://www.luogu.org/problemnew/show/P3733 原本以为要线段树分治+LCT,查了查发现环上的值直 ... 
- 【LibreOJ】#6396. 「THUPC2018」弗雷兹的玩具商店 / Toyshop   线段树+完全背包
		[题目]#6396. 「THUPC2018」弗雷兹的玩具商店 / Toyshop [题意]给定一个长度为n的物品序列,每个物品有价值.不超过m的重量.要求支持以下三种操作:1.物品价值区间加减,2.物 ... 
- loj#2312. 「HAOI2017」八纵八横(线性基 线段树分治)
		题意 题目链接 Sol 线性基+线段树分治板子题.. 调起来有点自闭.. #include<bits/stdc++.h> #define fi first #define se secon ... 
- LOJ 121 「离线可过」动态图连通性——LCT维护删除时间最大生成树 / 线段树分治
		题目:https://loj.ac/problem/121 离线,LCT维护删除时间最大生成树即可.注意没有被删的边的删除时间是 m+1 . 回收删掉的边的节点的话,空间就可以只开 n*2 了. #i ... 
- 「LuoguP3865」 【模板】ST表 (线段树
		题目背景 这是一道ST表经典题——静态区间最大值 请注意最大数据时限只有0.8s,数据强度不低,请务必保证你的每次查询复杂度为 O(1) 题目描述 给定一个长度为 N 的数列,和 M 次询问,求出每一 ... 
- 「BZOJ1537」Aut – The Bus(变形Dp+线段树/树状数组 最优值维护)
		网格图给予我的第一反应就是一个状态 f[i][j] 表示走到第 (i,j) 这个位置的最大价值. 由于只能往下或往右走转移就变得显然了: f[i][j]=max{f[i-1][j], f[i][j-1 ... 
- LOJ 3094 「BJOI2019」删数——角标偏移的线段树
		题目:https://loj.ac/problem/3094 弱化版是 AGC017C . 用线段树维护那个题里的序列即可. 对应关系大概是: 真实值的范围是 [ 1-m , n+m ] :考虑设偏移 ... 
- 「luogu4462」[CQOI2018] 异或序列
		「luogu4462」[CQOI2018]异或序列 一句话题意 输入 \(n\) 个数,给定\(k\),共 \(m\) 组询问,输出第 \(i\) 组询问 \(l_i\) \(r_i\) 中有多少个连 ... 
随机推荐
- 高性能 Jsonpath 框架,Snack3 3.2.29 发布
			Snack3,一个高性能的 JsonPath 框架 借鉴了 Javascript 所有变量由 var 申明,及 Xml dom 一切都是 Node 的设计.其下一切数据都以ONode表示,ONode也 ... 
- C# 读写文件从用户态切到内核态,到底是个什么流程?
			一:背景 1. 一个很好奇的问题 我们在学习 C# 的过程中,总会听到一个词叫做 内核态 ,比如说用 C# 读写文件,会涉及到代码从 用户态 到 内核态 的切换,用 HttpClient 获取远端的数 ... 
- QT软件工程师招聘市场需求报告
			QT软件工程师招聘市场需求报告 目录 最流行的编程语言排行榜 QT软件工程师职位需求 QT软件工程师薪资待遇 QT软件工程师行业需求 QT软件工程师QT技术需求 QT软件工程师基础技术需求 QT软件工 ... 
- oracle-安装与访问、卸载
			安装oracle 官网(http://oracle.com/ )下载oracle -->Oracle Database -->点击接受Accept --> 下载11g(Downloa ... 
- 从 1.5 开始搭建一个微服务框架——日志追踪 traceId
			你好,我是悟空. 前言 最近在搭一个基础版的项目框架,基于 SpringCloud 微服务框架. 如果把 SpringCloud 这个框架当做 1,那么现在已经有的基础组件比如 swagger/log ... 
- Spring-03
			1. AOP相关概念 1.1 AOP概念&作用 AOP(Aspect Oriented Programming)是一种思想,面向切面编程 作用:在不修改源码的前提下,在程序运行过程中对方法进行 ... 
- sudoer文件配置错误修复
			以错误配置权限为例,如果是sudoer文件内容配置错误,替换步骤(4)中相关命令即可 (1)建立两个ssh连接,分别记为A.B (2)A:echo $$获取ID (3)B:pkttyagent --p ... 
- HMS Core安全检测服务如何帮助大学新生防范电信诈骗?
			一年一度的高考结束了,很多学生即将离开父母,一个人踏入大学生活,但由于人生阅历较少,容易被不法分子盯上. 每年开学季也是大一新生遭受诈骗的高峰期,以下是一些常见的案例.有的骗子会让新生下载注册一些恶意 ... 
- mvc url重写
			public class newDomainRoute : Route { private Regex domainRegex; private Regex pathRegex; public str ... 
- AtCoder Beginner Contest 247 F - Cards // dp + 并查集
			原题链接:F - Cards (atcoder.jp) 题意: 给定N张牌,每张牌正反面各有一个数,所有牌的正面.反面分别构成大小为N的排列P,Q. 求有多少种摆放方式,使得N张牌朝上的数字构成一个1 ... 
