首页 > 其他分享 >P8339 [AHOI2022] 钥匙 思考--zhengjun

P8339 [AHOI2022] 钥匙 思考--zhengjun

时间:2023-07-12 21:36:48浏览次数:43  
标签:bg -- AHOI2022 P8339 stk int void ed top

很容易考虑到计算贡献。

该问题的关键在于——如何使得钥匙和宝箱的对应关系不算重

Warning:有这样的二元对应关系,可以考虑一下转化为括号序列!

转化为括号序列之后,发现路径上括号串的对应关系能够预处理出来。

套个虚树和扫描线,就做完了。

代码

#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int N=5e5+10,M=1e6+10;
int n,m,a[N],b[N];
vector<int>A[N];
int dft,bg[N],ed[N],dep[N],fa[N];
namespace QTree{
	int dft,pos[N],top[N],son[N],siz[N];
	void dfs1(int u){
		dep[u]=dep[fa[u]]+1,siz[u]=1;
		for(int v:A[u])if(v^fa[u]){
			fa[v]=u,dfs1(v);
			siz[u]+=siz[v];
			if(siz[v]>siz[son[u]])son[u]=v;
		}
	}
	void dfs2(int u,int t){
		top[u]=t,pos[bg[u]=++dft]=u;
		if(son[u])dfs2(son[u],t);
		for(int v:A[u])if(v^fa[u]&&v^son[u])dfs2(v,v);
		ed[u]=dft;
	}
	void init(){
		dfs1(1),dfs2(1,1);
	}
	int LCA(int u,int v){
		for(;top[u]^top[v];u=fa[top[u]]){
			if(dep[top[u]]<dep[top[v]])swap(u,v);
		}
		return dep[u]<dep[v]?u:v;
	}
	int kth(int u,int k){
		for(;dep[u]-dep[top[u]]<k;u=fa[top[u]])k-=dep[u]-dep[top[u]]+1;
		return pos[bg[u]-k];
	}
}
using QTree::LCA;
using QTree::kth;
vector<int>pos[N],B[N];
int top,stk[N];
void add(int u,int v){
	B[u].push_back(v),B[v].push_back(u);
}
int tag[N];
bool isin(int u,int t){
	return bg[t]<=bg[u]&&bg[u]<=ed[t];
}
struct opts{
	int l,r,x;
};
vector<opts>o[N];
void update(int x,int y,int l,int r){
	if(x>y||l>r)return;
	o[x].push_back({l,r,1}),o[y+1].push_back({l,r,-1});
}
void insert(int u,int v){
//	fprintf(stderr,"%d %d\n",u,v);
	if(isin(u,v)){
		int x=kth(u,dep[u]-dep[v]-1);
		update(bg[u],ed[u],1,bg[x]-1);
		update(bg[u],ed[u],ed[x]+1,n);
	}
	else if(isin(v,u)){
		int x=kth(v,dep[v]-dep[u]-1);
		update(1,bg[x]-1,bg[v],ed[v]);
		update(ed[x]+1,n,bg[v],ed[v]);
	}
	else{
		update(bg[u],ed[u],bg[v],ed[v]);
	}
}
void ins(int s,int u,int fa=0,int now=0){
	now+=tag[u];
	if(!now)return insert(s,u);
	for(int v:B[u])if(v^fa)ins(s,v,u,now);
}
void clr(int u,int fa=0){
	for(int v:B[u])if(v^fa)clr(v,u);
	B[u].clear();
}
void solve(vector<int>&p){
	if(p.empty())return;
	sort(p.begin(),p.end(),[](int x,int y){return bg[x]<bg[y];});
	stk[top=1]=p[0];
	for(int len=p.size(),i=1;i<len;i++){
		int x=LCA(stk[top],p[i]);
		for(;top>1&&dep[stk[top-1]]>=dep[x];top--)add(stk[top-1],stk[top]);
		if(stk[top]^x)add(x,stk[top--]);
		if(stk[top]^x)stk[++top]=x;
		if(stk[top]^p[i])stk[++top]=p[i];
	}
	for(int i=1;i<top;i++)add(stk[i],stk[i+1]);
	for(int u:p)tag[u]=3-a[u]*2;
	for(int u:p)if(tag[u]>0)ins(u,u);
	clr(stk[1]);
	for(int u:p)tag[u]=0;
}
namespace BIT{
	int c[N];
	void add(int x,int y){
		for(;x<=n;x+=x&-x)c[x]+=y;
	}
	void get(int x,int &y){
		for(y=0;x;x^=x&-x)y+=c[x];
	}
}
vector<pair<int,int> >q[N];
int ans[M];
int main(){
	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)scanf("%d%d",&a[i],&b[i]);
	for(int i=1,u,v;i<n;i++){
		scanf("%d%d",&u,&v);
		A[u].push_back(v),A[v].push_back(u);
	}
	QTree::init();
	for(int i=1;i<=n;i++)pos[b[i]].push_back(i);
	for(int i=1;i<=n;i++)solve(pos[i]);
	for(int i=1,u,v;i<=m;i++){
		scanf("%d%d",&u,&v);
		q[bg[u]].push_back({bg[v],i});
	}
	for(int i=1;i<=n;i++){
		for(opts x:o[i])BIT::add(x.l,x.x),BIT::add(x.r+1,-x.x);
		for(auto x:q[i])BIT::get(x.first,ans[x.second]);
	}
	for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
	return 0;
}

标签:bg,--,AHOI2022,P8339,stk,int,void,ed,top
From: https://www.cnblogs.com/A-zjzj/p/17548892.html

相关文章

  • 大型线段树 - 知识点梳理
    可持久化线段树可持久化数据结构可以通过不断重复利用节点,在高效且省空间的情况下建立及存储普通数据结构的多个历史版本并进行查询。因为存在时间轴,因此有时可搭配离线算法使用。实现方法所有树形数据结构的可持久化处理都和这个差不多普通的线段树长这样:假设要对其中一个......
  • Leangoo领歌Scrum工具标签升级,企业级标签组上线
    在Leangoo领歌敏捷工具中,标签通常用作对任务的分类,或任务的优先级区分等。这次我们发布了大家期待已久的“企业级标签组”功能,标签可以统一管理啦~之前,Leangoo的标签功能只限于单个看板使用,需要创建一个看板编辑一次标签,各个看板的标签是相互独立的,导致无法在企业内使用统一规范的......
  • 数据结构-链表带哨兵
    一.链表带哨兵importjava.util.Iterator;importjava.util.function.Consumer;//带哨兵publicclassshuju02implementsIterable<Integer>{//整体privateNodehead=newNode(666,null);//头指针​@Override​publicIterator<Integer>iterator(){​......
  • ipython的安装和简单使用
    前言ipython是一个python的交互式shell,比默认的pythonshell好用得多,支持变量自动补全,自动缩进,支持bashshell命令,内置了许多很有用的功能和函数。学习ipython将会让我们以一种更高的效率来使用python。同时它也是利用Python进行科学计算和交互可视化的一个最佳的平台安装pip......
  • Java学习day02:流程控制1
    我在B站上大学......
  • AtCoder Grand Contest 012 D Colorful Balls
    洛谷传送门AtCoder传送门不错的题。bxEnder32k。我们发现交换有传递性,那么我们能交换就连边,答案是\(\prod\frac{(sz)!}{\prodc_i!}\),其中\(sz\)为连通块大小,\(c_i\)为这个连通块中第\(i\)种颜色出现次数。于是我们得到了一个\(O(n^2)\)的做法。发现很多遍是无用的......
  • 全栈测试开发----unittest的设计及实现----自动化测试分层思想(1)
    通过unittest框架完成自动化分层操作,实现数据分离,减少代码于数据之间的依赖性,完成报告的生成并自动发送一系列操作。 前言:有人认为,在进行自动化测试过程中,测试代码只需要包含测试逻辑即可。其实不然,他需要包括很多类的代码,如URL拼接、访问UI控件、HTML/XML的解析等,如......
  • 110.成员初始化列表会在什么时候用到?它的调用过程是什么?
    110.成员初始化列表会在什么时候用到?它的调用过程是什么?1.当初始化一个引用成员变量时;structMyClass{constintmya;int&myb;MyClass(inta,int&b):mya(a),myb(b){}~MyClass(){}};2.当初始化一个非静态的常量成员时;inta=1;classMyClass{......
  • k8s 中的卷
    前面的文章我们分享了pod,RC,RS,DaemonSet,CJ,Service等各种资源今天我们来分享一波如何将磁盘挂载到容器中,在docker里面这种技术叫做数据卷,感兴趣的小伙伴可以查看一下文章:【Docker系列】docker学习六,探究一下数据卷容器对于一个pod,他有自己的CPU,RAM,网络接口等资源都是可......
  • 109.怎么快速定位错误出现的地方?
    109.怎么快速定位错误出现的地方?1.如果是简单的错误,可以直接双击错误列表里的错误项或者生成输出的错误信息中带行号的地方就可以让编辑窗口定位到错误的位置上。2.对于复杂的模板错误,最好使用生成输出窗口。多数情况下出发错误的位置是最靠后的引用位置。如果这样确定不了错......