[BZOJ 4763] 雪辉

题意

给定一棵 \(n\) 个点的无根树, 点带权. \(q\) 次询问, 每次给定树上的若干路径, 求这些路径上的点共有多少种不同权值以及这些点的权值组成的集合的 \(\operatorname{mex}\).

\(n,q\le1\times 10^5,v_i\le30000\). 部分测试点强制在线.

题解

首先吐槽一下沙雕考试出题人又出原题

这个只有 \(30000\) 的值域明示要用 std::bitset 趴...

然后发现这个 std::bitset 的标准接口不滋磁查 lowbit, 于是 \(\operatorname{mex}\) 就没法求了...(于是沙雕rvalue就手写了一个)

然后按照套路树剖一下把树链拆成 DFS 序上的 \(\log\) 段区间, 然后变成求若干段区间的 bitset 的并. 发现数据范围刚好允许开 \(O(n)\) 个 bitset, 那么直接对 DFS 序分块, 然后把一段连续的块的 bitset 都求出来, 这样查询的时候就可以只处理两端的散块了.

对于一次查询, 首先树剖出若干个区间, 然后发现这一坨区间可能有很多重复, 我们随手排个序把相交的区间都并起来. 直接在预处理好的连续块数据上增量构造就可以了.

时间复杂度好像是 \(O\left(n\left(\sqrt n+\frac V w\right)+q\left(\sqrt n\log n+\frac V w\right)\right)\). 实测跑得巨快无比. 大概是因为复杂度中 \(O(q \sqrt n \log n)\) 的部分因为无法造出每条树链长度都达到 \(O(\sqrt n)\) 的同时剖出来的树链数量达到 \(\log n\) 的路径而跑不满趴(树链数量增加必然导致整树深度变浅)...神仙 hzoizcl 说这个那个 \(O(\sqrt n \log n)\) 实际只能达到 \(O\left(\log\left (\sqrt n^{\sqrt n}\right)\right)\) 级别qaq...(这个值大概是 \(2\texttt{k}\) 左右于是复杂度好像没毛病)

参考代码

#include <bits/stdc++.h>

const int SQRN=320;
const int MAXV=1e5+10;
const int MAXE=2e5+10;
typedef unsigned int uint; struct Edge{
int from;
int to;
Edge* next;
};
Edge E[MAXE];
Edge* head[MAXV];
Edge* topE=E; struct Bits{
static const int MAXL=940;
uint data[MAXL];
Bits(){}
inline void operator|=(const Bits& b){
for(int i=0;i<MAXL;i++)
this->data[i]|=b.data[i];
}
inline int count(){
int ans=0;
for(int i=0;i<MAXL;i++)
ans+=__builtin_popcount(this->data[i]);
return ans;
}
inline int mex(){
for(int i=0;i<MAXL;i++){
if(__builtin_popcount(this->data[i])!=32){
for(int j=0;j<32;j++)
if(((this->data[i]>>j)&1)==0)
return (i<<5)|j;
}
}
return MAXL<<5;
}
inline void set(int p){
this->data[p>>5]|=(1u<<(p&31));
}
};
Bits s[SQRN][SQRN];
Bits ans; int n;
int q;
int clk;
int sqrn;
int blk[MAXV];
int dfn[MAXV];
int val[MAXV];
int pos[MAXV];
int prt[MAXV];
int top[MAXV];
int son[MAXV];
int deep[MAXV];
int size[MAXV]; int cur;
std::pair<int,int> R[MAXV]; void Merge();
void DFS(int,int);
void Export(int,int);
inline int ReadInt();
void DFS(int,int,int);
inline void Insert(int,int); int main(){
int T;
n=ReadInt(),q=ReadInt(),T=ReadInt();
sqrn=sqrt(n+0.5);
for(int i=1;i<=n;i++)
val[i]=ReadInt();
for(int i=1;i<n;i++){
int a=ReadInt(),b=ReadInt();
Insert(a,b);
Insert(b,a);
} DFS(1,0,0);
DFS(1,1); for(int i=0;i*sqrn<n;i++){
for(int j=i;j*sqrn<n;j++){
if(j>i)
s[i][j]=s[i][j-1];
for(int k=j*sqrn;blk[k]==j&&k<n;k++)
s[i][j].set(val[pos[k]]);
}
} // Query;
int lastans=0;
for(int i=0;i<q;i++){
memset(ans.data,0,sizeof(ans.data));
int cnt=ReadInt();
cur=0;
while(cnt--){
int a=ReadInt()^(lastans*T),b=ReadInt()^(lastans*T);
Export(a,b);
}
Merge();
for(int i=0;i<cur;i++){
int l=R[i].first,r=R[i].second;
if(blk[l]==blk[r]){
for(int i=l;i<=r;i++)
ans.set(val[pos[i]]);
}
else{
if(blk[l]<blk[r]-1)
ans|=s[blk[l]+1][blk[r]-1];
for(int i=l;blk[i]==blk[l];i++)
ans.set(val[pos[i]]);
for(int i=r;blk[i]==blk[r];i--)
ans.set(val[pos[i]]);
}
// printf("%d %d %d\n",ans.data[0],ans.data[1],ans.data[2]);
}
int x=ans.count(),y=ans.mex();
printf("%d %d\n",x,y);
lastans=x+y;
}
return 0;
} void Export(int x,int y){
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]])
std::swap(x,y);
R[cur++]=std::make_pair(dfn[top[x]],dfn[x]);
x=prt[top[x]];
}
if(deep[x]>deep[y])
std::swap(x,y);
R[cur++]=std::make_pair(dfn[x],dfn[y]);
} void Merge(){
int cnt=cur;
std::sort(R,R+cnt);
int l=R[0].first,r=R[0].second;
for(int i=1;i<cnt;i++){
if(R[i].first>r){
R[cur++]=std::make_pair(l,r);
l=R[i].first;
r=R[i].second;
}
else
r=std::max(r,R[i].second);
}
R[cur++]=std::make_pair(l,r);
} void DFS(int root,int prt,int deep){
::prt[root]=prt;
::deep[root]=deep;
::size[root]=1;
for(Edge* i=head[root];i!=NULL;i=i->next){
if(i->to!=prt){
DFS(i->to,root,deep+1);
size[root]+=size[i->to];
if(size[i->to]>size[son[root]])
son[root]=i->to;
}
}
} void DFS(int root,int top){
::dfn[root]=clk;
::pos[clk]=root;
::blk[clk]=clk/sqrn;
++clk;
::top[root]=top;
if(son[root])
DFS(son[root],top);
for(Edge* i=head[root];i!=NULL;i=i->next)
if(i->to!=son[root]&&i->to!=prt[root])
DFS(i->to,i->to);
} inline void Insert(int from,int to){
topE->from=from;
topE->to=to;
topE->next=head[from];
head[from]=topE++;
} inline int ReadInt(){
int x=0;
register char ch=getchar();
while(!isdigit(ch))
ch=getchar();
while(isdigit(ch)){
x=x*10+ch-'0';
ch=getchar();
}
return x;
}

[BZOJ 4763]雪辉的更多相关文章

  1. 洛谷P3603 || bzoj 4763 雪辉 && bzoj4812: [Ynoi2017]由乃打扑克

    https://www.luogu.org/problemnew/show/P3603 https://www.lydsy.com/JudgeOnline/problem.php?id=4763 就是 ...

  2. Bzoj4763 雪辉

    Time Limit: 39 Sec  Memory Limit: 666 MBSubmit: 151  Solved: 80 Description 上次立下的NOIP退役Flag没有成功   这次 ...

  3. [bzoj4763]雪辉&[bzoj4812][Ynoi2017]由乃打扑克

    来自FallDream的博客,未经允许,请勿转载,谢谢. cut掉部分题面. 给一个n个点的树,点有点权,有m次询问,每次询问多条链的并有多少种不同的点权以及它的mex mex就是一个集合中最小的没有 ...

  4. 「BZOJ4763」雪辉

    「BZOJ4763」天野雪辉 题目大意:有一棵 \(n\) 个点的树,树上每一个点有权值 \(a_i \leq 30000\) ,每次询问给出若干路径,求出这些路径的并上面的不同颜色数与 \(mex\ ...

  5. BZOJ 4763

    有毒 第一开始一直RE,我就把dfs改成了bfs 结果一直TLE,自己造的数据要跑8s 因为 lxl 等人讲随机 $\sqrt{n}$ 个点作为关键点就可以了 但是我把随机改成深度有关就AC了,而且那 ...

  6. [题解] 洛谷 P3603 雪辉

    模拟赛中遇到了这个题,当时我这个沙雕因为把一个\(y\)打成了\(x\)而爆零.回来重新写这道题,莫名其妙的拿了rank1... 我的解法与其他几位的题解有些不同我太蒻了.并没有选取所谓的关键点,而是 ...

  7. MVC |分部视图 PartialView()

    介绍如何定义 其实它和普通视图没有多大区别,只是创建分部视图的时候视图里没有任何内容,你需要什么标签你自己加.第二就是分部视图不会执行_ViewStart.cshtml中的内容) 控制器 Partia ...

  8. 【刷题】洛谷 P3613 睡觉困难综合征

    题目背景 刚立完Flag我就挂了WC和THUWC... 时间限制0.5s,空间限制128MB 因为Claris大佬帮助一周目由乃通过了Deus的题,所以一周目的由乃前往二周目世界找雪辉去了 由于二周目 ...

  9. [Bzoj4722]由乃(线段树好题)(倍增处理模数小快速幂)

    4722: 由乃 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 360  Solved: 131[Submit][Status][Discuss] D ...

随机推荐

  1. JAVA里的VO、BO、PO分别指什么?

    VO(value object) 值对象 通常用于业务层之间的数据传递,和PO一样也是仅仅包含数据而已.但应是抽象出的业务对象,可以和表对应,也可以不,这根据业务的需要.个人觉得同DTO(数据传输对象 ...

  2. .NET中OpenFileDialog使用报线程错误的解决方法

    昨天,在做一个NPOI读取的小demo的时候,使用OpenFileDialog打开文件,最开始的写法,直接在按钮点击事件中写,会报错,代码如下: OpenFileDialog ofd = new Op ...

  3. 自己写一个java的mvc框架吧(四)

    自己写一个mvc框架吧(四) 写一个请求的入口,以及初始化框架 上一章写了获取方法的入参,并根据入参的参数类型进行数据转换.这时候,我们已经具备了通过反射调用方法的一切必要条件.现在我们缺少一个htt ...

  4. UI-12组结对编程作业总结

    UI-12组结对编程作业总结 源码Github地址 https://github.com/tilmto/TILMTO/tree/master/Arithmetic 作业摘要 本次结对编程作业分为以下两 ...

  5. js-redux学习笔记2

    1.为了 dispatch 一个 action,我们需要一个 dispatch 函数.可以用一个 action creator 去发送一个 action. var setNameActionCreat ...

  6. vue webpack 打包后css背景图路径问题

    最近在写vue-webpack项目时,打包后遇到了css背景图片路径报错的问题 奇怪的是,通过img标签引入的图片路径却没有问题,看来是webpack在打包后,读取css中图片的相对路径出错了. 稍微 ...

  7. 纯小白入手 vue3.0 CLI - 2.1 - 组件 ( component )

    vue3.0 CLI 真小白入手全教程系列:https://www.cnblogs.com/ndos/category/1295752.html 我的 github 地址 - vue3.0Study  ...

  8. 除虫记之C#调用C函数出现的诡异错误

     作者:朱金灿 来源:http://blog.csdn.net/clever101 同事反映在在项目中使用C#程序调用我们部门编写的C++模块出现一个诡异错误:在调用A算法失败后,其它算法均不能调 ...

  9. Html5+离线打包创建本地消息

    自己离线打包Html5+ Runtime,通常是导入SDK的Hello实例,然后修改.在做消息通知功能时,使用push.createMessage不起作用. 首先参考Android平台离线打包推送插件 ...

  10. 绝版Node--Sequlize搭建服务(Node全栈之路)

    绝版Node--Sequlize搭建服务(Node全栈之路) 参考资料:https://itbilu.com/nodejs/npm/VkYIaRPz-.html 准备环境:Mysql,Node 前沿: ...