ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【题解】「JOISC 2018 Day 3」比太郎的聚会

2021-10-06 16:01:29  阅读:258  来源: 互联网

标签:10 int 题解 复杂度 sqrt JOISC 2018 预处理 define


「JOISC 2018 Day 3」比太郎的聚会

\(\text{Solution:}\)

一定要看好数据范围!!!

从这题里面学到了太多……

  • 注意到连边一定是小点往大点连的,所以一定没有环

  • 询问总量是固定的,总输入量是 \(2\times 10^5\) 级别。

看到这里起码可以正常想题了……

首先,如果我们去暴力,那不难想到一个直接从点 \(x\) 往外暴力扩展的做法。这个做法的时间复杂度是 \(O(n).\)

那么,有没有其他想法?是不是可以预处理一下答案?我们发现如果要预处理的话,至少需要 \(O(n^2)\) 的复杂度。

注意如何预处理:我们需要从小到大枚举点,按照从前到后的顺序,把前面更新过的点维护的点集归并到这个点上,这样复杂度才是最低的。

那么两个做法都过不了,考虑中和一下。

我们可以用预处理的方式处理每个点距离最远的 \(O(\sqrt{n})\) 个点,然后对于询问大于 \(\sqrt{n}\) 的询问,我们发现,输入总量是固定的! 也就是说,这种询问不会超过 \(\sqrt{n}\) 次。

所以综上,我们就可以做到一个 \(O(n\sqrt{n})\) 的解法了。

#include<bits/stdc++.h>
using namespace std;
const int N=4e5+10;
int n,m,Q,in[N],B,qr[N];
typedef pair<int,int> pr;
vector<pr>bk[N];
vector<int>G[N];
inline void link(int x,int y){G[x].push_back(y);}
inline int Max(int x,int y){return x>y?x:y;}
char buf[1<<21],*p1=buf,*p2=buf;
char obuf[1<<21],*O=obuf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
inline int read(){
	int s=0,w=1;
	char ch=getchar();
	while(!isdigit(ch)){
		if(ch=='-')w=-1;
		ch=getchar();
	}
	while(isdigit(ch)){
		s=s*10-'0'+ch;
		ch=getchar();
	}
	return s*w;
}
inline void write(int x){
	if(x<0){
		x=-x;
		*O++='-';
	}
	if(x>9)write(x/10);
	*O++=x%10+'0';
}
#define mk make_pair
#define fi first
#define se second
vector<pr>pv,pu;
int vis[N];
void Do(){
	for(int i=1;i<=n;++i){
		bk[i].push_back(mk(0,i));
		for(int j=0;j<(int)G[i].size();++j){
			int v=G[i][j];
			pv.clear();
			for(int k=0;k<(int)bk[v].size();++k)pv.push_back(mk(bk[v][k].fi+1,bk[v][k].se));
			pu.resize(bk[i].size()+bk[v].size());
			merge(bk[i].begin(),bk[i].end(),pv.begin(),pv.end(),pu.begin(),greater<pr>());
			bk[i].clear();
			for(int k=0;k<pu.size()&&bk[i].size()<B;++k)
				if(!vis[pu[k].se])vis[pu[k].se]=1,bk[i].push_back(pu[k]);
			for(int k=0;k<(int)bk[i].size();++k)vis[bk[i][k].se]=0;
		}
	}
}
int f[N];
int solve(int x){
	for(int i=1;i<=n;++i)f[i]=-(1<<30);
	f[x]=0;
	int ans=-1;
	for(int i=x;i>=1;--i){
		if(!vis[i])ans=Max(ans,f[i]);
		for(int j=0;j<(int)G[i].size();++j)f[G[i][j]]=Max(f[G[i][j]],f[i]+1);
	}
	return ans;
}
int main(){
	n=read();m=read();Q=read();
	for(int i=1;i<=m;++i){
		int u=read(),v=read();
		link(v,u);
	}
	B=320;Do();
	while(Q--){
		int root=read(),num=read();
		for(int i=1;i<=num;++i){qr[i]=read();vis[qr[i]]=1;}
		if(num<B){
			int res=-1;
			for(int i=0;i<(int)bk[root].size();++i){
				if(!vis[bk[root][i].se]){res=bk[root][i].fi;break;}
			}
			write(res);*O++='\n';
		}
		else {
			write(solve(root));
			*O++='\n';
		}
		for(int i=1;i<=num;++i)vis[qr[i]]=0;
	}
	fwrite(obuf,O-obuf,1,stdout);
	return 0;
}

标签:10,int,题解,复杂度,sqrt,JOISC,2018,预处理,define
来源: https://www.cnblogs.com/h-lka/p/15371486.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有