Description

Solution

标算我并不会...

考虑一种根号思想

首先以 \(1\) 为根dfs整棵树

那么在任意时刻一个点的儿子的权值种类最多只会有 \(\sqrt m\) 种。

可以在每个点维护一个邻接表,存储这个点的儿子们的所有权值种类,以及该权值出现次数。

考虑如何支持修改

如果要对点 \(x\) 进行修改

首先要改它的父亲 \(fa\),就要找到它父亲的父亲 \(y\) ,因为 \(fa\) 是 \(y\) 的儿子,\(fa\) 的信息储存在了 \(y\) 邻接表里。

具体是在 \(y\) 的邻接表中找到 \(fa\) 当前的权值 \(val\),然后把这个点的出现次数 \(-1\)。再把 \(val+1\) 的出现次数 \(+1\)。这样就完成了对 \(fa\) 权值的修改。

然后改点 \(x\) 的所有儿子就比较方便了,直接遍历 \(x\) 的邻接表,把所有点的权值 \(+1\) 就好了。

看上去就做完了,但是我们还不能支持查询任意一个点当前的权值。因为邻接表存的是一个个"等价类",是无法区分具体的点的。

所以我们还需要在每个点维护两个标记方便我们快速知道真正的点权,具体是维护 \(tag[i],tag2[i]\) 分别表示修改过点 \(i\) 的儿子们多少次和点 \(i\) 的儿子们修改过多少次。这样 \(tag[i]+tag2[i]\) 就是点 \(i\) 的真实权值了。

时间复杂度 \(O(m\sqrt m)\) 但远远达不到上界。

还跑了个rank1

Code

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using std::min;
using std::max;
using std::swap;
using std::vector;
typedef double db;
typedef long long ll;
#define pb(A) push_back(A)
#define pii std::pair<int,int>
#define all(A) A.begin(),A.end()
#define mp(A,B) std::make_pair(A,B)
const int N=5e5+5;
const ll mod=1000109107; ll tot=0;
int tag[N],tag2[N];
int n,m,son[N],fa[N]; struct Edge{
int to,nxt,sze;
}; struct G{
int dp[N],dc;
int head[N],cnt;
Edge edge[N*20]; void del(int x){
dp[++dc]=x;
} int newnode(){
return dc?dp[dc--]:++cnt;
} void add(int x,int y,int z=0){
int t=newnode();
edge[t].to=y;
edge[t].nxt=head[x];
edge[t].sze=z;
head[x]=t;
} }A,B; int getint(){
int X=0,w=0;char ch=getchar();
while(!isdigit(ch))w|=ch=='-',ch=getchar();
while( isdigit(ch))X=X*10+ch-48,ch=getchar();
if(w) return -X;return X;
} void dfs(int now){
for(int i=A.head[now];i;i=A.edge[i].nxt){
int to=A.edge[i].to;
if(to==fa[now]) continue;
fa[to]=now;son[now]++;
dfs(to);
}
} signed main(){
freopen("cactus.in","r",stdin);freopen("cactus.out","w",stdout);
n=getint(),m=getint();
for(int i=1;i<n;i++){
int x=getint(),y=getint();
A.add(x,y),A.add(y,x);
} dfs(1);
fa[1]=n+1;son[n+1]=1;
for(int i=1;i<=n+1;i++)
if(son[i])
B.add(i,0,son[i]);
for(int cas=1;cas<=m;cas++){
int x=getint(),ans=0;
if(x>1){
int y=fa[fa[x]],val=tag[y]+tag2[fa[x]];
for(int las=0,i=B.head[y];i;las=i,i=B.edge[i].nxt){
if(B.edge[i].to==val){
if(B.edge[i].sze>1)
B.edge[i].sze--;
else if(las)
B.edge[las].nxt=B.edge[i].nxt,B.del(i);
else
B.head[y]=B.edge[i].nxt,B.del(i);
break;
}
} ans=val+1;
int flag=0;
for(int i=B.head[y];i;i=B.edge[i].nxt){
if(B.edge[i].to==ans){
B.edge[i].sze++;
flag=1; break;
}
} if(!flag)
B.add(y,ans,1);
} for(int i=B.head[x];i;i=B.edge[i].nxt){
B.edge[i].to++;
if(B.edge[i].sze&1) ans^=B.edge[i].to;
} (tot+=1ll*ans*((1ll*cas*cas%mod+cas)%mod)%mod)%=mod;
tag[x]++;tag2[fa[x]]++;
} printf("%lld\n",tot);
return 0;
}

[JZOJ5984] 仙人掌的更多相关文章

  1. jzoj5984. 【北大2019冬令营模拟2019.1.1】仙人掌 (分块)

    题面 题解 数据结构做傻了.jpg 考虑每一个节点,它的儿子的取值最多只有\(O(\sqrt {m})\)种,那么可以用一个双向链表维护儿子的所有取值以及该取值的个数,那么对儿子节点修改一个值就是\( ...

  2. bzoj1023: [SHOI2008]cactus仙人掌图

    学习了一下圆方树. 圆方树是一种可以处理仙人掌的数据结构,具体见这里:http://immortalco.blog.uoj.ac/blog/1955 简单来讲它是这么做的:用tarjan找环,然后对每 ...

  3. 【BZOJ 1023】【SHOI 2008】cactus仙人掌图

    良心的题解↓ http://z55250825.blog.163.com/blog/static/150230809201412793151890/ tarjan的时候如果是树边则做树形DP(遇到环就 ...

  4. 【BZOJ-1952】城市规划 [坑题] 仙人掌DP + 最大点权独立集(改)

    1952: [Sdoi2010]城市规划 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 73  Solved: 23[Submit][Status][ ...

  5. 【BZOJ-4316】小C的独立集 仙人掌DP + 最大独立集

    4316: 小C的独立集 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 57  Solved: 41[Submit][Status][Discuss] ...

  6. 仙人掌(cactus)

    仙人掌(cactus) Time Limit:1000ms Memory Limit:64MB 题目描述 LYK 在冲刺清华集训(THUSC) !于是它开始研究仙人掌,它想来和你一起分享它最近研究的 ...

  7. 【bzoj1023】仙人掌图

    [bzoj1023]仙人掌图 题意 给一棵仙人掌,求直径. \(n\leq 100000\) 分析 分析1:[Tarjan]+[环处理+单调队列优化线性dp]+[树形dp] 分开两种情况处理: ①环: ...

  8. hdu3594 强连通(仙人掌图)

    题意:给定一张有向图,问是否是仙人掌图.仙人掌图的定义是,首先,这张图是一个强连通分量,其次所有边在且仅在一个环内. 首先,tarjan可以判强连通分量是否只有一个.然后对于所有边是否仅在一个环内,我 ...

  9. 【BZOJ】【1023】【SHOI2008】cactus仙人掌图

    DP+单调队列/仙人掌 题解:http://hzwer.com/4645.html->http://z55250825.blog.163.com/blog/static/150230809201 ...

随机推荐

  1. assetBundle 中的prefeb资源图片显示粉色方框

    assetBundle打包的资源是有平台属性的,当移动端iOS或者Android AssetBundle资源 在editor 加载的时候,比如TextMeshPro中的字体就不能正确加载 pc端调试, ...

  2. Integer 与int的区别

    1.在的model的时候很多喜欢用int 类型 但是最好用Integer类型因为在查询的时候如果返回不到数据 Model就会报这个类是空的 所以应该尽量选用interger

  3. Django高级篇三。restful的解析器,认证组件,权限组件

    一.rest=framework之解析器 1)解析器作用. 根据提交的数据.只解析某些特定的数据.非法数据不接收,为了系统安全问题 比如解析的数据格式有 有application/json,x-www ...

  4. (PMP)第13章-----项目相关方管理

    13.1 识别相关方 1 相关方分类的方法: 1.1 权力/利益方格,权力/影响方格,影响/作用方格(小型项目,关系简单) 权力:基于相关方的职权级别: 利益:对项目成果的关心程度 影响:对项目成果的 ...

  5. adb Android Debug Bridge 安卓调试桥

    adb devices 获取设备列表及设备状态 adb get-state 获取设备的状态,设备的状态有 3 钟,device , offline , unknown device:设备正常连接 of ...

  6. Reading | 《Linux就该这么学》

    目录 一.前言 1.Linux概念 2.RPM(红帽软件包管理器) 3.Yum软件仓库 二.常用Linux命令 1.Shell 2.命令基本格式和man命令 3.常用系统工作命令 echo命令 dat ...

  7. Chapter7 抑癌基因

    一.实验证明,如果肿瘤不是肿瘤病毒产生时,与正常细胞融合后,其恶性表型是隐形的 二. 家族性视网膜母细胞瘤的形成模型 如何使得一个细胞获得两个突变(两次随机的突变可能性太小) 模型一:有丝分裂的同源重 ...

  8. bash编程-正则表达式

    正则表达式与通配符有部分相似之处,但正则表达式更复杂也更强大. 通配符用于(完全)匹配文件名,支持通配符的命令有:ls.find.cp等: 正则表达式用于在文件中(包含)匹配字符串,支持的命令有:gr ...

  9. java之vector详细介绍

    1 vector介绍 Vector简介 Vector 是矢量队列,它是JDK1.0版本添加的类.继承于AbstractList,实现了List, RandomAccess, Cloneable这些接口 ...

  10. electron 使用 node-ffi 调用 C++ 动态链接库(DLL)

    一.为什么需要使用DLL 需要使用系统 API 操作或扩展应用程序: 需要调用第三方的接口API,特别是与硬件设备进行通信,而这些接口 API 基本上都是通过 C++ 动态链接库(DLL)实现的: 需 ...