• BZOJ5288 [Hnoi2018]游戏


    BZOJ5288 [HNOI/AHOI2018]游戏

    题目看这里

    题解

    对于20分,我们可以暴力搞,往返跑,反正怎么都能过。
    对于(x<=y)的40分的点,就是网上熟悉的倒着跑,就可以AC的做法。
    对于一个点,我们处理出它左右可以到达的最大区间。对于这个特殊性质,我们很容易的想到从后往前跑,因为打开它的钥匙一定在前面,那么我们每次访问一个点,跳到它后面序号比它大的那个点的最右区间,看是否能往前扩展,这样每个点的遍历就是(O(n))的了。
    然而出题人据说为了卡另一种情况,没卡这一个。

    对于满分做法。(口胡的,玄学多好啊
    考虑一下对于60分的贪心,我们发现。
    因为是从后到前,所以我们不会重复的去处理区间,以此来达到(O(n))
    对于满分,我们也是这样处理,
    为了不重复处理区间,对于满分,我们考虑一下拓扑排序,为什么?
    我们考虑这样建边,如果钥匙在当前门的左边,(add(i+1,i)),右边,(add(i,i+1)),表示我们当前无法走到这边,那么我们就可以从底层开始处理出小区间,以此拓展,每个点不会重复访问,时间复杂度为(O(n))
    调了我一晚上qwq,发现一个问题,对于入队,我们优先序号大的会快不少,原因是出题人造的数据基本门和钥匙相等,其实按照这样的建边规则,因为是优先区间小的,然后更新大的,所以其实拓扑的时候还是要记录一下的?

    Code

    Ps:这个代码是我在洛谷题解上看的,问题很大,但是过了。。。
    魔改了一天,想清楚了还是要记录每个点然后在一个一个向上更新,算了不改了。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<cmath>
    #include<queue>
    using namespace std;
    const int N=1e6+5;
    queue<int>q;
    int n,m,T,id[N];
    int key[N],l[N],r[N],in[N];
    int num,head[N];
    struct node{
    	int to,nex;
    }e[N<<1];
    int read(){
    	int x=0,w=1;char ch=getchar();
    	while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    	return x*w;
    }
    
    void add(int from,int to){
    	num++;
    	e[num].to=to;
    	e[num].nex=head[from];
    	head[from]=num;
    }
    
    int main(){
    	n=read();m=read();T=read();
    	for(int i=1;i<=m;i++){
    		int x=read(),y=read();key[x]=y;
    		if(x>=y)add(x+1,x),in[x]++;else add(x,x+1),in[x+1]++;
    	}
    	for(int i=n;i>=1;i--){
    		if(!key[i]&&i!=n)id[i]=id[i+1],l[id[i]]=i;
    		else l[i]=i,r[i]=i,id[i]=i;
    	}
    	for(int i=1;i<=n;i++){
    		l[i]=l[id[i]];r[i]=r[id[i]];
    	}
    	for(int i=n;i>=1;i--)if(!in[i])q.push(i);
    	while(!q.empty()){
    		int u=q.front(),f=1;q.pop();
    		for(int i=head[u];i;i=e[i].nex){
    			{in[e[i].to]--;if(!in[e[i].to])q.push(e[i].to);}
    		}
    		while(f){
    			f=0;
    		while(l[u]>1&&(!key[l[u]-1]||(key[l[u]-1]>=l[u]&&key[l[u]-1]<=r[u])))
    				l[u]=l[l[u]-1],f=1;
    			while(r[u]<n&&(!key[r[u]]||(key[r[u]]>=l[u]&&key[r[u]]<=r[u])))
    				r[u]=r[r[u]+1],f=1;
    		}
    	
    	}
    	while(T--){
    		int x=read(),y=read(); 
    		if(l[x]<=y&&r[x]>=y)
    			printf("YES
    ");
    		else printf("NO
    ");
    	}
    	return 0;
    }
    
  • 相关阅读:
    ios中静态库的创建和使用、制作通用静态库(Cocoa Touch Static Library)
    ios-字符串替换-正则表达式-例子
    Android 中自定义仪表盘
    Android中控件AutoCompleteTextView的使用方法和一些属性
    用代码如何检测一个android程序是否在运行
    android 报错: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v4/animation/AnimatorCompatHelper;
    android中Zing二维码扫描,二维码生成
    gps数据上传防止android系统休眠
    Android中判断service是否在运行
    BottomSheetDialogFragment 如何设置高度和禁止滑动
  • 原文地址:https://www.cnblogs.com/hhh1109/p/10388369.html
Copyright © 2020-2023  润新知