BZOJ4644: 经典傻逼题【线段树分治】【线性基】
Description
这是一道经典傻逼题,对经典题很熟悉的人也不要激动,希望大家不要傻逼。
考虑一张N个点的带权无向图,点的编号为1到N。 对于图中的任意一个点集
(可以为空或者全集),所有恰好有一个端点在这个点集中的边组成的集合被称
为割。 一个割的权值被定义为所有在这个割上的边的异或和。
一开始这张图是空图, 现在,考虑给这张无向图不断的加边, 加入每条边之
后,你都要求出当前权值最大的割的权值, 注意加入的边永远都不会消失。
Input
输入的第一行包括一个数ID表示数据编号, 如第一组数据中的ID = 1。注意
样例数据中的ID = 0。
接下来的第一行包括两个整数N,M表示图的点数和总共加的边。
接下来M行,每行三个正整数x,y,w表示在点x和点y之间加入一条权值为w的边。
注意x和y可能相同,两条不同的边也可能连接了同一对点。
此外, w将以二进制形式从高位向低位给出,比如, 6 = 110(2),因此如果边
权为 6,那么w将会是110。
1 ≤ N≤ 500, 1 ≤ M ≤ 1000, 0 ≤ L < 1000, 1 ≤ x,y≤ N
Output
输出M行,按顺序输出每一条边加入之后权值最大的割的权值。
同样,你也要以二进制形式输出,形式和输入格式中描述的形式一样。
Sample Input
0
3
6
1 2 1
1 2 1
3 3 111
1 3 101101
1 2 1011
2 3 111011
Sample Output
1
0
0
101101
101101
110000
HINT
前三条边加入之后的答案较为显然,考虑后三条边,加入第六条边之前, 考
虑点集{1,2},它对应的割只有第四条边, 因此答案就是第四条边的权值,考虑加
入最后一条边以后的情况,此时点集{1,2}对应的割变成了第四条边和第六条边组
成的集合,权值也发生了相应的改变。 点集{2}对应的割是第五条边和第六条边
组成的集合, 可以证明这就是权值最大的割,权值为\(1011(2)\bigoplus111011(2) =110000(2)\)
要是不知道啥是线段树分治,啥是线性基,这题这辈子不可能会做出来的
但是身为一个菜鸡,就算知道了我也照样做不出来
毕竟还是一道很好的题
很巧妙地运用了线段树分治这个方法,也让我对模型的转化有了更加深刻的认识
思路
因为直接维护边的权值非常的不方便
而且异或又有一些神奇的性质吗,所以可以考虑把边的权值转移到点上
如果一条边的两个端点都被选择了那么显然是这条边没有贡献
那就让每个点的权值等于连接到这个点上的所有边的权值的异或和
这样显然选出来点集和割的贡献就是点集权值的异或和
所以就只需要考虑点了
那么因为会像图中加入新的边,所以每个点在每个时间的权值可能是不一样的,所以就考虑用线段树分治来实现
这样就只需要算出每个时间对应的最大值就可以了
这个东西可以维护一个线性基来做
然后就做完了
我真是个傻逼
//Author: dream_maker
#include<bits/stdc++.h>
using namespace std;
//----------------------------------------------
//typename
typedef long long ll;
//convenient for
#define fu(a, b, c) for (int a = b; a <= c; ++a)
#define fd(a, b, c) for (int a = b; a >= c; --a)
#define fv(a, b) for (int a = 0; a < (signed)b.size(); ++a)
//inf of different typename
const int INF_of_int = 1e9;
const ll INF_of_ll = 1e18;
//fast read and write
template <typename T>
void Read(T &x) {
bool w = 1;x = 0;
char c = getchar();
while (!isdigit(c) && c != '-') c = getchar();
if (c == '-') w = 0, c = getchar();
while (isdigit(c)) {
x = (x<<1) + (x<<3) + c -'0';
c = getchar();
}
if (!w) x = -x;
}
template <typename T>
void Write(T x) {
if (x < 0) {
putchar('-');
x = -x;
}
if (x > 9) Write(x / 10);
putchar(x % 10 + '0');
}
//----------------------------------------------
const int N = 1e3 + 10;
const int LEN = 1e3;
typedef bitset<N> bittyp;
void Read(bittyp &x) {
static char s[N];
scanf("%s", s);
int len = strlen(s);
reverse(s, s + len);
x.reset();
fu(i, 0, len - 1) x[i] = s[i] - '0';
}
void Write(bittyp x) {
if (!x.any()) {
putchar('0');
return;
}
int pos;
fd(i, LEN, 0) if (x.test(i)) {
pos = i;
break;
}
fd(i, pos, 0) {
if (x.test(i)) putchar('1');
else putchar('0');
}
}
struct Basis {
bittyp b[N];
void clear() {
fu(i, 0, LEN) b[i].reset();
}
void insert(bittyp x) {
fd(i, LEN, 0) {
if (x[i]) {
if (!b[i].any()) {
b[i] = x;
break;
}
x ^= b[i];
}
}
}
bittyp query_max() {
bittyp res;
fd(i, LEN, 0) {
if (!res[i] && b[i].any()) {
res ^= b[i];
}
}
return res;
}
};
#define LD (t << 1)
#define RD (t << 1 | 1)
vector<bittyp> g[N << 2];
void modify(int t, int l, int r, int ql, int qr, bittyp vl) {
if (ql <= l && r <= qr) {
g[t].push_back(vl);
return;
}
int mid = (l + r) >> 1;
if (qr <= mid) modify(LD, l, mid, ql, qr, vl);
else if (ql > mid) modify(RD, mid + 1, r, ql, qr, vl);
else {
modify(LD, l, mid, ql, mid, vl);
modify(RD, mid + 1, r, mid + 1, qr, vl);
}
}
void dfs(int t, int l, int r, Basis now) {
fv(i, g[t]) now.insert(g[t][i]);
if (l == r) {
Write(now.query_max());
putchar('\n');
return;
}
int mid = (l + r) >> 1;
dfs(LD, l, mid, now);
dfs(RD, mid + 1, r, now);
}
int n, m;
int las[N];
bittyp val[N];
int main() {
int ID; Read(ID);
Read(n), Read(m);
fu(i, 1, m) {
int u, v; bittyp w;
Read(u), Read(v), Read(w);
if (u == v) continue;
if (las[u]) modify(1, 1, m, las[u], i - 1, val[u]);
las[u] = i, val[u] ^= w;
if (las[v]) modify(1, 1, m, las[v], i - 1, val[v]);
las[v] = i, val[v] ^= w;
}
fu(i, 1, n) modify(1, 1, m, las[i], m, val[i]);
Basis rt;
rt.clear();
dfs(1, 1, m, rt);
return 0;
}
BZOJ4644: 经典傻逼题【线段树分治】【线性基】的更多相关文章
- $CF938G\ Shortest\ Path\ Queries$ 线段树分治+线性基
正解:线段树分治+线性基 解题报告: 传送门$QwQ$ 考虑如果只有操作3,就这题嘛$QwQ$ 欧克然后现在考虑加上了操作一操作二 于是就线段树分治鸭 首先线段树叶子节点是询问嘛这个不用说$QwQ$. ...
- BZOJ.4184.shallot(线段树分治 线性基)
BZOJ 裸的线段树分治+线性基,就是跑的巨慢_(:з」∠)_ . 不知道他们都写的什么=-= //41652kb 11920ms #include <map> #include < ...
- 【luogu3733】【HAOI2017】 八纵八横 (线段树分治+线性基)
Descroption 原题链接 给你一个\(n\)个点的图,有重边有自环保证连通,最开始有\(m\)条固定的边,要求你支持加边删边改边(均不涉及最初的\(m\)条边),每一次操作都求出图中经过\(1 ...
- LOJ 2312(洛谷 3733) 「HAOI2017」八纵八横——线段树分治+线性基+bitset
题目:https://loj.ac/problem/2312 https://www.luogu.org/problemnew/show/P3733 原本以为要线段树分治+LCT,查了查发现环上的值直 ...
- 【线段树分治 线性基】luoguP3733 [HAOI2017]八纵八横
不知道为什么bzoj没有HAOI2017 题目描述 Anihc国有n个城市,这n个城市从1~n编号,1号城市为首都.城市间初始时有m条高速公路,每条高速公路都有一个非负整数的经济影响因子,每条高速公路 ...
- BZOJ4644 : 经典傻逼题
设每个点的权值为和它相连的所有边的权值的异或和,那么等价于选若干个点,使得点权异或和最大,这显然只需要维护一组线性基,然后从高位到低位贪心选取即可. 对于本题,因为有修改操作,所以考虑按时间分治,并用 ...
- Codeforces 938G 线段树分治 线性基 可撤销并查集
Codeforces 938G Shortest Path Queries 一张连通图,三种操作 1.给x和y之间加上边权为d的边,保证不会产生重边 2.删除x和y之间的边,保证此边之前存在 3.询问 ...
- BZOJ4184:shallot(线段树分治,线性基)
Description 小苗去市场上买了一捆小葱苗,她突然一时兴起,于是她在每颗小葱苗上写上一个数字,然后把小葱叫过来玩游戏. 每个时刻她会给小葱一颗小葱苗或者是从小葱手里拿走一颗小葱苗,并且 让小葱 ...
- bzoj 4184 shallot——线段树分治+线性基
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4184 本来想了可持久化trie,不过空间是 nlogn (出一个节点的时候把 tot 复原就 ...
随机推荐
- NodeJS学习笔记五
Promise简介 所谓Promise,就是一个对象,用来传递异步操作的消息. Promise对象有以下两个特点. (1)对象的状态不受外界影响.Promise对象代表一个异步操作,有三种状态:Pen ...
- #C++初学记录(并查集)
并查集 题目 今天是伊格那丢的生日.他邀请了很多朋友.现在该吃晚饭了.伊格那丢想知道他至少需要多少张桌子.你必须注意到并不是所有的朋友都认识对方,而且所有的朋友都不想和陌生人待在一起.这个问题的一个重 ...
- bzoj2733 / P3224 [HNOI2012]永无乡(并查集+线段树合并)
[HNOI2012]永无乡 每个联通块的点集用动态开点线段树维护 并查集维护图 合并时把线段树也合并就好了. #include<iostream> #include<cstdio&g ...
- 20145105 《Java程序设计》第5周学习总结
20145105 <Java程序设计>第5周学习总结 教材学习内容总结 第八章 异常处理 一.语法与继承架构 (一)使用try.catch 执行流程 尝试执行try区块中程序代码 如果出现 ...
- linux实践--字符集
一.ASCII码 首先懂得ASCII码表 二 八 十 十六 缩写/字符 0000 0000 0 0 00 NUL(null) 0000 0001 1 1 01 SOH(start of headlin ...
- [fastjson] - fastjson中 JSONObject 和 JSONArray
/** * 对jsonObject对象进行key的获取 * @param jsonObject */ public ArrayList<String> jsonKeyRecursion(J ...
- calcite介绍
前言 calcite是一个可以将任意数据查询转换成基于sql查询的引擎,引擎特性也有很多,比如支持sql树的解析,udf的扩展,sql执行优化器的扩展等等.目前已经被很多顶级apache项目引用,比如 ...
- 2016"百度之星" - 初赛(Astar Round2A) A.All X 矩阵快速幂
All X Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Problem Des ...
- mac 下安装 express
express为js的后端框架, 终端 >>> npm install -g express-generator 然后cd到您要创建项目的目录之下,输入 >>> ...
- 安装 android x86 到 virtual box
由于vmware无论怎么整,声音都出不了. 改用virtual box了. 很多注意点都参照了这篇文章 http://www.android-x86.org/documents/virtualboxh ...