博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Luogu3733 HAOI2017 八纵八横 线段树分治、线性基
阅读量:5070 次
发布时间:2019-06-12

本文共 3439 字,大约阅读时间需要 11 分钟。


拿出一棵生成树,一个合法的环的权值就是若干个只有一条边不在生成树上的环的权值。

因为最开始的边不会被删除,所以最开始预处理出一棵生成树,加边、删边的时候就直接加入、删除一个环,我们只需维护如何异或上若干个环的权值使得总权值最大。

不难发现这个可以线性基做,把所有环的权值丢入线性基,这个最大权值就是线性基能够表示的最大值。我们只需要加边和删边的时候将这个环的权值在线性基中加入或删除。

发现线性基不支持删除,所以线段树分治做即可。

复杂度\(O(qlogq\frac{1000^2}{w})\)

#include
//this code is written by Itstusing namespace std;const int _ = 1007;#define BS bitset < 1001 >struct Edge{ int end , upEd; BS val;}Ed[_ << 1];struct BASE{ BS now[1001]; void insert(BS x){ for(int i = 1000 ; i >= 0 ; --i) if(x[i]) if(now[i][i]) x ^= now[i]; else return (void)(now[i] = x); } BS query(){ BS cur; for(int i = 1000 ; i >= 0 ; --i) if(now[i][i] && !cur[i]) cur ^= now[i]; return cur; }};int head[507] , pre[_] , s[_] , t[_] , cntEd = 1 , cnt , N , M , Q;BS val[_];vector < BS > now[_ << 2];void input(BS &x){ x.reset(); string s; cin >> s; for(int i = (int)s.size() - 1 ; i >= 0 ; --i) x[i] = s[s.size() - i - 1] - '0';}void addEd(int a , int b , const BS c){ Ed[++cntEd] = (Edge){b , head[a] , c}; head[a] = cntEd;}void getEd(int id){ cin >> s[id] >> t[id]; input(val[id]);}#define mid ((l + r) >> 1)#define lch (x << 1)#define rch (x << 1 | 1)void add(int x , int l , int r , int L , int R , const BS &val){ if(l >= L && r <= R) return (void)now[x].emplace_back(val); if(mid >= L) add(lch , l , mid , L , R , val); if(mid < R) add(rch , mid + 1 , r , L , R , val);}BS up[_]; int dep[_];void dfs(int x , int uped){ for(int i = head[x] ; i ; i = Ed[i].upEd) if(i != (uped ^ 1)) if(dep[Ed[i].end]){ if(dep[x] <= dep[Ed[i].end]) add(1 , 0 , Q , 0 , Q , up[Ed[i].end] ^ up[x] ^ Ed[i].val); } else{ dep[Ed[i].end] = dep[x] + 1; up[Ed[i].end] = up[x] ^ Ed[i].val; dfs(Ed[i].end , i); }}void output(BS x){ if(x.none()){puts("0"); return;} bool flg = 0; for(int i = 1000 ; i >= 0 ; --i) if(flg |= x[i]) putchar(x[i] + '0'); putchar('\n');}void solve(int x , int l , int r , BASE &all){ for(auto t : now[x]) all.insert(t); if(l == r) return output(all.query()); const BASE t = all; solve(lch , l , mid , all); all = t; solve(rch , mid + 1 , r , all); all = t;}int main(){#ifndef ONLINE_JUDGE freopen("in","r",stdin); //freopen("out","w",stdout);#endif ios::sync_with_stdio(0); cin >> N >> M >> Q; for(int i = 1 ; i <= M ; ++i){ getEd(0); addEd(s[0] , t[0] , val[0]); addEd(t[0] , s[0] , val[0]); } dep[1] = 1; dfs(1 , 0); for(int i = 1 ; i <= Q ; ++i){ string str; cin >> str; if(str == "Add"){getEd(++cnt); pre[cnt] = i;} else if(str == "Cancel"){ int id; cin >> id; add(1 , 0 , Q , pre[id] , i - 1 , val[id] ^ up[s[id]] ^ up[t[id]]); pre[id] = 0; } else{ int id; cin >> id; BS tp; input(tp); add(1 , 0 , Q , pre[id] , i - 1 , val[id] ^ up[s[id]] ^ up[t[id]]); pre[id] = i; val[id] = tp; } } for(int i = 1 ; i <= cnt ; ++i) if(pre[i]) add(1 , 0 , Q , pre[i] , Q , val[i] ^ up[s[i]] ^ up[t[i]]); BASE empty; for(int i = 1000 ; i >= 0 ; --i) empty.now[i].reset(); solve(1 , 0 , Q , empty); return 0;}

转载于:https://www.cnblogs.com/Itst/p/10941942.html

你可能感兴趣的文章
一网打尽各类Java基本数据类型转换
查看>>
FlowLayout布局
查看>>
深入理解JVM读书笔记--字节码执行引擎
查看>>
vue-搜索功能-实时监听搜索框的输入,N毫秒请求一次数据
查看>>
批处理 windows 服务的安装与卸载
查看>>
React文档翻译 (快速入门)
查看>>
nodejs fs路径
查看>>
动态规划算法之最大子段和
查看>>
linux c:关联变量的双for循环
查看>>
深入浅出理解zend framework(三)
查看>>
python语句----->if语句,while语句,for循环
查看>>
javascript之数组操作
查看>>
LinkedList源码分析
查看>>
TF-IDF原理
查看>>
用JS制作博客页面背景随滚动渐变的效果
查看>>
JavaScript的迭代函数与迭代函数的实现
查看>>
一步步教你学会browserify
查看>>
Jmeter入门实例
查看>>
亲近用户—回归本质
查看>>
中文脏话识别的解决方案
查看>>