(2016北京集训十三)【xsy1533】mushroom - bitset

题解:
神题。。。我看到的时候直接吓懵了。。。
这是一道STL题。。。否则可能要写可持久化ETT或者可持久化Toptree?
用bitset来维护每个蘑菇上哪里有杂草,那么
对于操作1和操作2:可以预处理每个点为跟的bitset;
对于操作3和操作4:预处理两个点到根这条链上的bitset,先异或再或两个点的lca的bitset;
对于操作5和操作6:直接暴力区间清零即可;
询问直接贪心,由于随机所以复杂度O(玄学)(实际上应该是$O(\frac{n}{32}+\frac{n}{ln200})$?)
用STL的bitset会T掉一个点。。。所以我只能看着dalao们的手写bitset瑟瑟发抖(然而也并没有完全看懂)
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#include<map>
#define inf 2147483647
#define eps 1e-9
using namespace std;
typedef long long ll;
typedef unsigned int uint;
struct edge{
int v,next;
}a[];
int n,m,u,v,op,L,now,cnt=,tot=,lg[],dep[],head[],rts[],fa[][];
uint *bt[],s1[][],s2[][];
map<uint*,int>mp;
void New(int k){
bt[++cnt]=bt[k];
mp[bt[cnt]]++;
}
void clr(int l,int r){
if(r-l<){
for(int i=l;i<=r;i++){
bt[now][i>>]&=~((uint)<<(i&));
}
return;
}
int L=(l>>)+,R=(r>>)-;
for(int i=L;i<=R;i++)bt[now][i]=;
for(int i=l;(i>>)!=L;i++)bt[now][i>>]&=~((uint)<<(i&));
for(int i=r;(i>>)!=R;i--)bt[now][i>>]&=~((uint)<<(i&));
}
void rec(int k){
if(mp[bt[k]]>){
uint *bb=bt[k];
bt[k]=(uint*)malloc(L*sizeof(uint));
mp[bt[k]]++;
for(int i=;i<L;i++)bt[k][i]=bb[i];
mp[bt[k]]--;
}
}
void Or(uint a[],uint b[]){for(int i=;i<L;i++)a[i]|=b[i];}
void And(uint a[],uint b[]){for(int i=;i<L;i++)a[i]&=b[i];}
void Nand(uint a[],uint b[]){for(int i=;i<L;i++)a[i]&=~b[i];}
void AND(uint a[],uint b[],uint c[],int k){
uint t=a[k>>]>>(k&)&;
for(int i=;i<L;i++)a[i]&=b[i]^c[i];
a[k>>]|=t<<(k&);
}
void NAND(uint a[],uint b[],uint c[],int k){
for(int i=;i<L;i++)a[i]&=~(b[i]^c[i]);
a[k>>]&=~((uint)<<(k&));
}
void add(int u,int v){
a[++tot].v=v;
a[tot].next=head[u];
head[u]=tot;
}
void dfs(int u,int ff,int dpt){
dep[u]=dpt;
fa[u][]=ff;
for(int i=;i<=;i++)fa[u][i]=fa[fa[u][i-]][i-];
for(int i=;i<L;i++)s1[u][i]=s1[ff][i];
s1[u][u>>]^=(uint)<<(u&);
for(int tmp=head[u];tmp!=-;tmp=a[tmp].next){
int v=a[tmp].v;
if(v!=ff){
dfs(v,u,dpt+);
}
}
s2[u][u>>]^=(uint)<<(u&);
for(int i=;i<L;i++)s2[ff][i]|=s2[u][i];
}
int lca(int u,int v){
if(dep[u]<dep[v])swap(u,v);
int l=dep[u]-dep[v];
for(int i=;i>=;i--){
if((<<i)&l)u=fa[u][i];
}
if(u==v)return u;
for(int i=;i>=;i--){
if(fa[u][i]!=fa[v][i]){
u=fa[u][i],v=fa[v][i];
}
}
return fa[u][];
}
int query(int k){
int ans=;
for(int i=;i<=n;){
if(bt[now][i>>]>>(i&)){
uint t=(bt[now][i>>]>>(i&(uint)))<<(i&),tt=t&-t;
//printf("%lld %lld %lld\n",(ll)bt[now][i>>5],(ll)t,(ll)tt);
if(tt>)tt=lg[tt>>]+;
else tt=lg[tt];
ans++;
i=((i&(~(uint)))|tt)+k+;
}else i=((i>>)+)<<;
}
return ans;
}
int main(){
memset(head,-,sizeof(head));
scanf("%d",&n);
for(int i=;i<n;i++){
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
L=(n+)>>;
for(int i=;i<=;i++)lg[<<i]=i;
bt[]=(uint*)malloc(L*sizeof(uint));
bt[]=(uint*)malloc(L*sizeof(uint));
for(int i=;i<L;i++)bt[][i]=bt[][i]=;
for(int i=;i<=n;i++)bt[][i>>]|=(uint)<<(i&);
dfs(,,);
scanf("%d",&m);
for(int i=;i<=m;i++){
scanf("%d%d",&op,&now);
switch(op){
case :{New(now);break;}
case :{
scanf("%d",&u);
rec(now);
Or(bt[now],bt[u]);
break;
}
case :{
scanf("%d",&u);
rec(now);
Nand(bt[now],s2[u]);
break;
}
case :{
scanf("%d",&u);
rec(now);
And(bt[now],s2[u]);
break;
}
case :{
scanf("%d%d",&u,&v);
rec(now);
NAND(bt[now],s1[u],s1[v],lca(u,v));
break;
}
case :{
scanf("%d%d",&u,&v);
rec(now);
AND(bt[now],s1[u],s1[v],lca(u,v));
break;
}
case :{
scanf("%d%d",&u,&v);
rec(now);
clr(u,v);
break;
}
case :{
scanf("%d%d",&u,&v);
rec(now);
clr(,u-),clr(v+,n);
break;
}
case :{
scanf("%d",&u);
printf("%d\n",query(u));
break;
}
}
}
return ;
}
(2016北京集训十三)【xsy1533】mushroom - bitset的更多相关文章
- (2016北京集训十三)【xsy1531】魔法游戏 - Nim游戏
题解: 好题!我的结论很接近正解了... 把一个数化成二进制,每次至少要拿走一位,最多全拿走,不能不拿.那么这就是一个经典的Nim问题了,子树异或起来就是根节点的答案,随便递推一下就行了. 代码: # ...
- (2016北京集训十三)【xsy1532】网络战争 - 最小割树+树上倍增+KD树
题解: 好题!! 这题似乎能上我代码长度记录的前五? 调试时间长度应该也能上前五QAQ 首先题目要求的明显就是最小割,当然在整个森林上求Q次最小割肯定是会GG的,所以我们需要一个能快速求最小割的算法— ...
- (2016北京集训十)【xsy1528】azelso - 概率期望dp
北京集训的题都是好题啊~~(于是我爆0了) 注意到一个重要的性质就是期望是线性的,也就是说每一段的期望步数可以直接加起来,那么dp求出每一段的期望就行了... 设$f_i$表示从$i$出发不回到$i$ ...
- 【2016北京集训】Mushroom
Portal --> broken qwq Description 一开始有个蘑菇,蘑菇里面有\(n\)个房间,是一棵有根树,\(1\)号是根,每个房间里面都有杂草,现在要支持以下操作:将某个指 ...
- 2016北京集训测试赛(十三) Problem B: 网络战争
Solution KD tree + 最小割树
- [2016北京集训试题6]mushroom-[bitset]
Description Solution bitset是个好东西啊..强行压位什么的真是够orz. 由于所有的蘑菇上房间的长相是一样的,我们针对每个房间,算出它到根节点的bitset和以它为根的子树的 ...
- 【2016北京集训测试赛(十)】 Azelso (期望DP)
Time Limit: 1000 ms Memory Limit: 256 MB Description 题解 状态表示: 这题的状态表示有点难想...... 设$f_i$表示第$i$个事件经过之 ...
- 【2016北京集训测试赛(二)】 thr (树形DP)
Description 题解 (这可是一道很早就碰到的练习题然后我不会做不想做,没想到在Contest碰到欲哭无泪......) 题目大意是寻找三点对的个数,使得其中的三个点两两距离都为d. 问题在于 ...
- 【2016北京集训测试赛(八)】 crash的数列 (思考题)
Description 题解 题目说这是一个具有神奇特性的数列!这句话是非常有用的因为我们发现,如果套着这个数列的定义再从原数列引出一个新数列,它居然还是一样的...... 于是我们就想到了能不能用多 ...
随机推荐
- php基础-----常量const和define的区别
1.常量是一个简单的标识符,在脚本运行期间,值不可改变,默认大小写敏感. 答:使用const使得代码简单易读,const本身就是一个语言结构,而define是一个函数.另外const在编译时要比def ...
- 使用 Shiro 设计基于用户、角色、权限的通用权限管理系统
一.前言 在大型的信息管理系统中,经常涉及到权限管理系统 下面来个 demo,很多复杂的系统的设计都来自它 代码已经放到github上了,地址:https://github.com/larger5/s ...
- Prime Distance POJ - 2689 线性筛
一个数 $n$ 必有一个不超过 $\sqrt n$ 的质因子. 打表处理出 $1$ 到 $\sqrt n$ 的质因子后去筛掉属于 $L$ 到 $R$ 区间的素数即可. Code: #include&l ...
- CF1041E Tree Reconstruction_构造_思维题
不难发现,每次询问结果一定是 (i,n)(i,n)(i,n), 而 iii 出现的次数恰好是 iii 到 i′i'i′ 的距离(i′i'i′ 是第一个不与 iii 相等的数).我们可以将这颗树构造成一 ...
- 路飞学城Python-Day20
[31.面向对象的软件开发与作业介绍] 1.面向对象分析(object oriented analysis ,OOA) 软件工程中的系统分析阶段,要求分析员和用户结合在一起,对用户的需求做出精确的分析 ...
- 【XSY2989】字符串
题目来源:NOI2018模拟测试赛(二十六) 题解: 首先由于这是个01串,所以反对称串的意思就是这个字符串的后半部分是前半部分的反转且翻转结果: 一个串出现有三种情况:在前半部分,在后半部分或穿过中 ...
- HDU 4535 吉哥系列故事——礼尚往来( 错排水题 )
链接:传送门 思路:错排模板题,水题是非常浪费时间的. /*********************************************************************** ...
- 倍增算法总结 ( 含RMQ模板)
部分题目来自<算法竞赛设计进阶> 问题 给定一个长度为n的数列A,有m个询问,每次给定一个整数T,求出最大的k,满足a[1],a[2]……a[k]的和小于等于T(不会打sigm ...
- AssetBundle打包优化解决方式
第一阶段:AssetBundle出一套解决方式 1.解决如今同一个资源打2个bundle的冗余问题 2.測试验证节省资源的比率是多少 问题拆分 一.bundle反复 问 题 :同样资源拆分问题? ...
- sql学习笔记(18)-----------数据库创建过程
手动创建数据库的步骤: 第一步:决定数据库实例的SID 数据库实例的SID用来将当前实例和以后可能创建的实例进行区分 % setenv ORACLE_SID mynewdb 第二步:建立数 ...