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 复原就 ...
随机推荐
- 关于c语言struct和typedef
C++中使用: struct test{ int x, y;};就可以定义一个名为 test的结构体,但C中很可能编译通不过.C语言并不支持在struct后使用标示符定义结构体的名字,test将 ...
- 20154312曾林 - Exp1 PC平台逆向破解
1.逆向及Bof基础实践说明 1.1-实践目标 对象:pwn1(linux可执行文件) 目标:使程序执行另一个代码片段:getshell 内容: 手工修改可执行文件,改变程序执行流程,直接跳转到get ...
- Python: 大型数组运算
需要在大数据集(比如数组或网格) 上面执行计算,涉及到数组的重量级运算操作,可以使用NumPy 库. 下面是一个简单的小例子,展示标准列表对象和NumPy 数组对象之间的差别 >>> ...
- Linux 查看系统所有用户
grep bash /etc/passwd Linux 查看系统所有用户
- IDEA,与gradle引入jar包报错
Warning:<i><b>root project 'netty_lecture': Unable to resolve additional project configu ...
- 前端面试题之 sum(2)(3) (链式调用,toString,柯里化,数组操作)
写一个函数让下面两个输出结果相同:console.log(sum(2)(3));console.log(sum(2,3)); var sum = (function() { var list = [] ...
- Web前端学习笔记之前端跨域知识总结
0x00 前言 相信每一个前端er对于跨域这两个字都不会陌生,在实际项目中应用也是比较多的.但跨域方法的多种多样实在让人目不暇接.老规矩,碰到这种情况,就只能自己总结一篇博客,作为记录. 0x01 什 ...
- K-Means 算法(Java)
kMeans算法原理见我的上一篇文章.这里介绍K-Means的Java实现方法,参考了Python的实现方法. 一.数据点的实现 package com.meachine.learning.kmean ...
- VS中子对话框的关闭回调函数
新建了QDialog的子类时,如果需要回调它的关闭函数 1.加入头文件#include <QCloseEvent> 2.重写函数 protected: void closeEvent(QC ...
- asp.net和.net的区别
http://zhidao.baidu.com/link?url=BEIkzsJqo-tnOmWKwzsiuXeohqVJzb_iRCZ5gWCozAGVdw2FSnWW95r3vaUAecUnKsW ...