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. win7访问局域网总提示用户名密码错误解决方案

    win7访问局域网总提示用户名密码错误解决方案 1.点击开始-在搜索栏输入:secpol.msc(或者直接按下win+r键,输入secpol.msc),打开本地安全策略. 2.找到“安全设置”的“本地 ...

  2. Linux 第十二天

    文件系统 1.分区类型 主分区:总共最多只能分四个 扩展分区:只能有一个,也算作主分区的一种,也就是说主分区加扩展分区最多有四个.但是扩展分区不能存储数据和格式化,必须再划分成逻辑分区才能使用. 逻辑 ...

  3. HTML5 添加新的标签 input属性

    <!-- 新增 有语意标签 --> <nav></nav> <!-- 导航标签 --> <seclion></seclion> ...

  4. 走进JDK(十)------HashMap

    有人说HashMap是jdk中最难的类,重要性不用多说了,敲过代码的应该都懂,那么一起啃下这个硬骨头吧!一.哈希表在了解HashMap之前,先看看啥是哈希表,首先回顾下数组以及链表数组:采用一段连续的 ...

  5. Hibernate 映射及查询

    实体类和实体之间的关系:一对多,多对多 数据库设计:e_r 一个实体对象就是一个表格,  如果是1对多的关系,将多方的主键拿到1方做外键.  多对多:重新建立一张新的表格,将双方的主键拿到这里做外键 ...

  6. ubuntu下签名命令

    Platform: RockchipOS: Android 6.0Kernel: 3.10.92 拷贝签名文件/signapk.jar和apk到同一目录下. 签名文件:rk3288/build/tar ...

  7. VS2015离线安装NuGet Package

    在一些情况下,VS2015直接安装NuGet Package的时候,速度异常缓慢: 所以还是考虑直接离线安装: Step1: 下载相应的Package https://www.nuget.org/ 然 ...

  8. Vuejs——(7)过渡(动画)

    版权声明:出处http://blog.csdn.net/qq20004604   目录(?)[+]   本篇资料来于官方文档: http://cn.vuejs.org/guide/transition ...

  9. HAProxy出现"远程主机强迫关闭了一个现有的连接 " 的错误及解决

    使用haproxy作为sql server 的负载均衡器. 使用了文档中的示例配置项: timeout client 50s        timeout server 50s 采用这个配置项,有时会 ...

  10. iOS编码规范(简版)

    1. 总体指导原则 [规则1-1]首先是为人编写程序,其次才是计算机. 说明:这是软件开发的基本要点,软件的生命周期贯穿产品的开发.测试.生产.用户使用.版本升级和后期维护等长期过程,只有易读.易维护 ...