BZOJ2322 [BeiJing2011]梦想封印 【set + 线性基】
题目链接
题解
鉴于BZOJ2115,要完成此题,就简单得多了
对图做一遍\(dfs\),形成\(dfs\)树,从根到每个点的路径形成一个权值,而每个返祖边形成一个环
我们从根出发去走一个环再回到根,最终会异或上环的权值而又回到根
所以环是可以任意选的
我们把环的权值丢进线性基,记线性基中有\(tot\)各位置,那么环的权值异或和方案数就是\(2^{tot}\)
我们将剩余路径权值放入线性基中消元后去重,剩余的路径权值是和线性基中的权值线性无关的
但路径只能选一个,记有\(x\)个线性无关的非\(0\)路径
除去\(0\),那么答案就是
\]
但这题动态删边,常规操作,离线改为加边
加边后有\(3\)种情况:
- 两端点都没访问过,那么不会产生任何影响
- 有一个端点访问过,那么现在就可以继续\(dfs\)到另一个没访问过的端点
- 两端点都访问过,就形成一个环,更新线性基即可
每次线性基被更新时,都要取出所有路径消一次元
每次路径加入集合前,都要放入线性基消元
集合去重用\(set\)即可
由于线性基只会被更新\(O(logw)\)次,路径只有\(O(nlogn)\)个
所以复杂度为\(O(nlognlogw)\)
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<map>
#include<set>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define cls(s,v) memset(s,v,sizeof(s))
#define mp(a,b) make_pair<int,int>(a,b)
#define cp pair<int,int>
using namespace std;
const int maxn = 50005,maxm = 100005,INF = 0x3f3f3f3f;
inline LL read(){
LL out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = 0; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 1) + (out << 3) + c - 48; c = getchar();}
return flag ? out : -out;
}
const int N = 63;
set<LL> S;
set<LL>::iterator it;
LL bin[maxn],d[maxn],A[70],c[maxn],ci,ansi,ans[maxn];
int tot,flag;
int n,m,Q,pos[maxn],out[maxn],q[maxn],vis[maxn];
int h[maxn],ne = 1,fa[maxn];
struct EDGE{int to,nxt,id; LL w;}ed[maxn << 1];
inline void build(int u,int v,int i,LL w){
ed[++ne] = (EDGE){v,h[u],i,w}; h[u] = pos[i] = ne;
ed[++ne] = (EDGE){u,h[v],i,w}; h[v] = ne;
}
bool ins(LL x){
for (int i = N; ~i; i--){
if (x & bin[i]){
if (!A[i]){A[i] = x; tot++; return true;}
else x ^= A[i];
}
}
return false;
}
LL check(LL x){
for (int i = N; ~i; i--) if ((x & bin[i]) && A[i]) x ^= A[i];
return x;
}
void dfs(int u){
vis[u] = true; LL x;
if (x = check(d[u])) S.insert(x);
Redge(u) if (!out[ed[k].id] && (to = ed[k].to) != fa[u]){
if (!vis[to]) fa[to] = u,d[to] = d[u] ^ ed[k].w,dfs(to);
else if (ins(d[to] ^ d[u] ^ ed[k].w)) flag = true;
}
}
void upd(){
if (!flag) return;
it = S.begin(); ci = 0;
while (it != S.end()) c[++ci] = *it,it++;
S.clear(); LL x;
for (int i = 1; i <= ci; i++)
if (x = check(c[i])) S.insert(x);
}
void rebuild(int k){
int u = ed[pos[k] ^ 1].to,v = ed[pos[k]].to; LL w = ed[pos[k]].w;
out[k] = false; flag = false;
if (!vis[u] && !vis[v]) return;
else if (vis[u]) fa[v] = u,d[v] = d[u] ^ w,dfs(v),upd();
else if (vis[v]) fa[u] = v,d[u] = d[v] ^ w,dfs(u),upd();
else ins(d[v] ^ d[u] ^ w),upd();
}
void print(){ans[ansi--] = 1ll * (S.size() + 1) * bin[tot] - 1;}
void work(){
upd(); print();
for (int i = Q; i; i--){
rebuild(q[i]);
print();
}
}
int main(){
bin[0] = 1; for (int i = 1; i <= N; i++) bin[i] = bin[i - 1] << 1ll;
n = read(); m = read(); Q = read();
int a,b; LL w;
REP(i,m){
a = read(); b = read(); w = read();
build(a,b,i,w);
}
REP(i,Q) out[q[i] = read()] = true;
ansi = Q; dfs(1);
work();
for (int i = 0; i <= Q; i++) printf("%lld\n",ans[i]);
return 0;
}
BZOJ2322 [BeiJing2011]梦想封印 【set + 线性基】的更多相关文章
- 【线性基】bzoj2322: [BeiJing2011]梦想封印
线性基的思维题+图常见套路 Description 渐渐地,Magic Land上的人们对那座岛屿上的各种现象有了深入的了解. 为了分析一种奇特的称为梦想封印(Fantasy Seal)的特技,需要引 ...
- 【BZOJ 2322】[BeiJing2011]梦想封印 利用"环基"+线性基特征值
很容易想到离线加边并且把环和链拆开搞(就是对于每个终点求出起点到他的路径(其实就是dfs树),然后bzoj2115),而且维护也很简单,然而我们发现不同的终点可能得到相同的值,这就是我们遇到的最大的问 ...
- BZOJ2322: [BeiJing2011]梦想封印
Description 渐渐地,Magic Land上的人们对那座岛屿上的各种现象有了深入的了解. 为了分析一种奇特的称为梦想封印(Fantasy Seal)的特技,需要引入如下的概念: 每一位魔法的 ...
- 【BZOJ2322】[BeiJing2011]梦想封印 高斯消元求线性基+DFS+set
[BZOJ2322][BeiJing2011]梦想封印 Description 渐渐地,Magic Land上的人们对那座岛屿上的各种现象有了深入的了解. 为了分析一种奇特的称为梦想封印(Fantas ...
- [BZOJ 2322][BeiJing2011]梦想封印
梦想封印 题意 原题面: Problem 2322. -- [BeiJing2011]梦想封印 2322: [BeiJing2011]梦想封印 Time Limit: 20 Sec Memory L ...
- BZOJ 2460: [BeiJing2011]元素 贪心,线性基
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2460 解法:从大到小排序,依次贪心的添加到当前集合就可以了,需要动态维护线性基.用拟阵证明 ...
- BZOJ_2460_[BeiJing2011]元素_线性基
BZOJ_2460_[BeiJing2011]元素_线性基 Description 相传,在远古时期,位于西方大陆的 Magic Land 上,人们已经掌握了用魔 法矿石炼制法杖的技术.那时人们就认识 ...
- [BeiJing2011]元素[贪心+线性基]
2460: [BeiJing2011]元素 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1245 Solved: 652[Submit][Stat ...
- BZOJ2460 [BeiJing2011]元素 【线性基】
2460: [BeiJing2011]元素 Time Limit: 20 Sec Memory Limit: 128 MB Submit: 1675 Solved: 869 [Submit][St ...
随机推荐
- Android应用安全之脆弱的加密
程序员希望通过加密来提升程序的安全性性,但却缺乏专业的密码学背景知识,使得应用对数据的保护非常薄弱.本文将介绍可能出现在Android应用中的一些脆弱的加密方式,以及对应的攻击方法. 造成脆弱加密的主 ...
- Python+Selenium爬取动态加载页面(2)
注: 上一篇<Python+Selenium爬取动态加载页面(1)>讲了基本地如何获取动态页面的数据,这里再讲一个稍微复杂一点的数据获取全国水雨情网.数据的获取过程跟人手动获取过程类似,所 ...
- Git配置用户名与邮箱
1.用户名和邮箱地址的作用 用户名和邮箱地址是本地git客户端的一个变量 每次commit都会用用户名和邮箱纪录. github的contributions统计就是按邮箱来统计的. 2.查看用户名和邮 ...
- ucosii笔记(一)
.ucosii是按照优先级高低来切换任务执行顺序的抢占式实时系统. 2.在被高优先级的任务抢占时,这个任务会将寄存器的数据(xPSR.PC.LR.R0.R1.R2.R3.R12等的值)存放在该任务自己 ...
- Linux随笔---tar命令
一.解压 语法:tar [主选项+辅选项] 文件或者目录 使用该命令时,主选项是必须要有的,它告诉tar要做什么事情,辅选项是辅助使用的,可以选用. 主选项:c:create:v:verbose: ...
- [BZOJ4379][POI2015]Modernizacja autostrady[树的直径+换根dp]
题意 给定一棵 \(n\) 个节点的树,可以断掉一条边再连接任意两个点,询问新构成的树的直径的最小和最大值. \(n\leq 5\times 10^5\) . 分析 记断掉一条边之后两棵树的直径为 \ ...
- 调用wx.request接口时需要注意的几个问题
写在前面 之前写了一篇<微信小程序实现各种特效实例>,上次的小程序的项目我负责大部分前端后台接口的对接,然后学长帮我改了一些问题.总的来说,收获了不少吧! 现在项目已经完成,还是要陆陆续续 ...
- BaseProxy:异步http/https中间人
BaseProxy 异步http/https代理,可拦截并修改报文,可以作为中间人工具.仅支持py3.5+.项目地址:BaseProxy. 意义 BaseProxy项目的本意是为了使HTTP/HTTP ...
- tornado学习笔记
一.UIMOTHODS: 1.在项目目录创建uimothods.py文件(名称可以任意)内容: def test2(self): return ('hello uimothods') 2.tornad ...
- live555学习(一)通读Makefile编译live555
live555学习(一)通读Makefile编译live555 live555 编译live555 学习开源 live555学习(一)通读Makefile编译live555 前言 live555简介 ...