【H - Parity game】

思路:

  • 关于本文中首次用到的一些STL函数,详见:FORMER_BLOG
  • 种类并查集+离散化
  • 这应该是一种非常简便的离散化方法:
    1. 因为数字的范围太大(1e9),不得不离散化,即将 5000*2index 通过映射存起来。
    2. 把每个询问存进结构体,数组和队列皆可;把全部的端点 index 存进 f 数组parvalmaxn 都是 1e4 + 5)。
    3. fsort 排序,unique 去重,如此,每个端点 index 就有了自己的 “指纹”
    4. 对每个询问,使用 lower_bound 寻找它的指纹,将它的指纹作为 l、r 进行并查集。

代码:

  • 141ms 912kB
//141ms		912kB


#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>

using namespace std;

const int maxn = 1e4 + 5;

int N,M;
int ans;
int par[maxn];
int val[maxn];
int f[maxn];int cnt;//存储所有用到的index 
struct NODE{
	int l,r,w;
	NODE(int l,int r,int w) : l(l) , r(r) , w(w) {} ;
};
queue<NODE> Q;

void INIT(){
	ans = 0;
	cnt = 0;
	memset(par , -1 , sizeof(par));
	memset(val , 0  , sizeof(val));
	return ;
}

int FIND(int i){
	if(par[i] == -1)
		return i;
	int tp = par[i];
	par[i] = FIND(par[i]);
	val[i] = (val[i] + val[tp]) % 2;
	return par[i];
}

void UNION(int w,int l,int r,int parl,int parr){
	par[parr] = parl;
	val[parr] = (val[l] + w - val[r] + 2) % 2;
	return ;
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	while(cin>>N>>M){
		INIT();
		for(int i=0;i<M;i++){
			int l,r,w;
			string str;
			cin>>l>>r>>str;
			if(str.size() == 3)
				w = 1;
			else
				w = 0;
			l--;
			Q.push(NODE(l,r,w));
			f[cnt++] = l;
			f[cnt++] = r;
		}
		sort(f , f+cnt);//排序
		int n = unique(f , f+cnt) - f;//1,2,3,4,5,1,1,2,2,3去重,得到去重后的元素个数
		while(Q.size()){
			NODE cur = Q.front() ; Q.pop() ;
			if(ans)
				continue;
			int w = cur.w ;
			int l = lower_bound(f , f+n , cur.l) - f;
			int r = lower_bound(f , f+n , cur.r) - f;//得到下标
			int parl = FIND(l);
			int parr = FIND(r);
			if(parl == parr)
				if((val[l] + w)%2 != val[r])
					ans = M - Q.size() - 1 ;
				else
					;
			else
				UNION(w , l , r , parl , parr);
		}
		if(!ans)
			ans = M;
		cout<<ans<<endl;
	} 
	return 0;
}

猜你喜欢

转载自blog.csdn.net/flash403/article/details/94554439