アイデア:
- 初めて使用STL関数紙のいくつかについては、以下を参照してください。FORMER_BLOGを。
- 互いに素セット離散+の種類
- これは非常に単純な離散方法でなければなりません。
- 範囲があまりにも大きな数字(1E9)であるので、我々は離散持っていた、およそされる5000 * 2のGe 指数によってマッピングが保存されました。
- 各質問は、構造内に堆積、およびキューJiekeのアレイと、すべてのエンドポイントは、インデックスは、に格納Fアレイ(PARとヴァルのMAXNがある1E4 + 5。 )。
- 以下の場合F:ソートソート、UNIQUEデエンファシス、各エンドポイントのように、インデックスは、自身の持っていた「指紋」 。
- 各クエリについて、使用LOWER_BOUNDをその指紋を見つけるために、それはのように指紋だL、Rは互いに素セット可能。
コード:
#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;
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;
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;
}