zoukankan      html  css  js  c++  java
  • 【题解】「JOISC 2018 Day 3」比太郎的聚会

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

    ( ext{Solution:})

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

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

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

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

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

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

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

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

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

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

    所以综上,我们就可以做到一个 (O(nsqrt{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++='
    ';
    		}
    		else {
    			write(solve(root));
    			*O++='
    ';
    		}
    		for(int i=1;i<=num;++i)vis[qr[i]]=0;
    	}
    	fwrite(obuf,O-obuf,1,stdout);
    	return 0;
    }
    
  • 相关阅读:
    Android设计模式系列-组合模式
    Android进阶之大话设计模式
    eclipse 安装lua插件
    防止应用被杀死
    lua string 库
    js与java通信
    一个祸害我很久的东东——事件过滤器之按键触发
    Qt主窗口
    新学期——新期望
    鱼C《零基础入门学习Python》10-17节课时知识点总结
  • 原文地址:https://www.cnblogs.com/h-lka/p/15371486.html
Copyright © 2011-2022 走看看