NOI 2015 & 洛谷1955 程序自动分析 【离散化+并查集】

题目来源:https://www.luogu.org/problemnew/show/P1955
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
★当时怎么没有写出这题,我**了

相关知识:

unique函数的用法:例子:unique(g+1,g+m+1)-g unique函数的作用就是去重(把重复的元素放在后面去)然后返回去重后(不考虑放在后面去的重复元素)的尾指针

lower_bound就是二分查找

思路:

关于等于或不等于,我们很容易想到把这些数 通过族群来区分,相等的就在一个族群(这就是并查集了)
但是你会发现这题数据特别大1e9了,单纯的并查集肯定不行了。
而这里的n却只有1e6,也就是说一共所给的x不会超过2e6,这里就要用到离散化
然后单独的按题目的输入顺序来处理还是有点逻辑上的麻烦,我们不妨先把等于号的处理完,在处理不等于的(先把能并在一起的族群并在一起,而不等于就是用来判断OK不OK)

注意:

第二份代码中 m=unique(g+1,g+m+1)-g-1;
我要说明一下我为什么减1,(因为好多人都没减),如果你的g数组是从1开始记录的 那么就需要减1,从0开始记录就不用,我这里的m的意思是 g的有效长度

代码:

首先上一个容易理解的(VJ上过了7500ms,但洛谷严格一些TLE)
v1存储相等的情况,v2存储不相等的情况
map的作用就是并查集

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<map>
#include<stack>
#include<queue>
#include<set>
using namespace std;
const int maxn=1e6+5;
const int mod=1e9+7;
typedef long long ll;
int n;
struct node
{
    int a,b,is;
};
map<int , int > m;
inline void read(int &x)
{
    char c;x=1;
    while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
    int res=c-'0';
    while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
    x*=res;
}
int seek(int k)
{
    return k==m[k]?k:m[k]=seek(m[k]);
}
int main()
{
    int t;read(t);
    while(t--){
        int n;read(n);
        m.clear();
        vector<node> v1,v2;
        while(n--){
            node t;read(t.a);read(t.b);read(t.is);
            m[t.a]=t.a;
            m[t.b]=t.b;
            if(t.is==0) v2.push_back(t);
            else v1.push_back(t);
        }
        for(int i=0;i<v1.size();i++){
            int x=seek(v1[i].a);
            int y=seek(v1[i].b);
            if(x!=y) m[x]=y;
        }
        bool flag=1;
        for(int i=0;i<v2.size();i++){
//            int k=seek(v2[i].a);
//            k=seek(v2[i].b);
            if(m[seek(v2[i].a)]==m[seek(v2[i].b)]){
                flag=0;
                break;
            }
        }
        if(flag) cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
    return 0;
}

然后这个是没有用map vector啥子之类的 写的,洛谷过了,用时(1800ms)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<map>
#include<stack>
#include<queue>
#include<set>
using namespace std;
const int maxn=1e6+5;
const int mod=1e9+7;
typedef long long ll;
int n,m;
struct node
{
    int a,b,is;
}f[maxn];
int g[maxn<<1],dad[maxn<<1];
inline void read(int &x)
{
    char c;x=1;
    while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
    int res=c-'0';
    while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
    x*=res;
}
bool cmp(node a,node b)
{
    return a.is>b.is;
}
int seek(int k)
{
    return k==dad[k]?k:dad[k]=seek(dad[k]);
}
int main()
{
    int t;read(t);
    while(t--){
        int n;read(n);
        m=0;
        for(int i=1;i<=n;i++){
            read(f[i].a);read(f[i].b);read(f[i].is);
            g[++m]=f[i].a;
            g[++m]=f[i].b;
        }
        sort(g+1,g+m+1);
        m=unique(g+1,g+m+1)-g-1;          //注意-1
        for(int i=1;i<=m;i++) dad[i]=i;
        for(int i=1;i<=n;i++){
            f[i].a=lower_bound(g+1,g+m+1,f[i].a)-g;
            f[i].b=lower_bound(g+1,g+m+1,f[i].b)-g;
        }
        sort(f+1,f+n+1,cmp);
        bool flag=1;
        for(int i=1;i<=n;i++){
            int x=seek(f[i].a);
            int y=seek(f[i].b);
            if(f[i].is==1){
                dad[x]=y;
            }
            else{
                if(x==y){
                    flag=0;
                    break;
                }
            }
        }
        if(flag) cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值