POJ - 1733 离散化 并查集

题意:求问数列区间奇偶信息正确与否

和上一题一样(甚至弱化),加个离散就ok啦

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<string>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#define rep(i,j,k) for(register int i=j;i<=k;i++)
#define rrep(i,j,k) for(register int i=j;i>=k;i--)
#define erep(i,u) for(register int i=head[u];~i;i=nxt[i])
#define iin(a) scanf("%d",&a)
#define lin(a) scanf("%lld",&a)
#define din(a) scanf("%lf",&a)
#define s0(a) scanf("%s",a)
#define s1(a) scanf("%s",a+1)
#define print(a) printf("%lld",(ll)a)
#define enter putchar(‘\n‘)
#define blank putchar(‘ ‘)
#define println(a) printf("%lld\n",(ll)a)
#define IOS ios::sync_with_stdio(0)
using namespace std;
const int maxn = 2e5+11;
const int oo = 0x3f3f3f3f;
const double eps = 1e-7;
typedef long long ll;
ll read(){
    ll x=0,f=1;register char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
int p[maxn],r[maxn];
void init(int n){
    memset(r,0,sizeof r);
    rep(i,0,n+2) p[i]=i;
}
int find(int x){
    if(x==p[x])return x;
    int oldp=p[x];
    int t=find(p[x]);
    r[x]=(r[x]+r[oldp])&1;
    return p[x]=t;
}
void link(int fa,int fb,int a,int b,int w){
    p[fb]=fa;
    r[fb]=(r[a]-r[b]+w+4)&1;
}
int b[maxn],n,m,tot;
struct P{
    int a,b;
    bool odd;
}a[maxn];
char s[66];
inline int pos(int i){
    return lower_bound(b+1,b+1+tot,i)-b;
}
int main(){
    while(cin>>n>>m){
        tot=0;
        rep(i,1,m){
            scanf("%d%d%s",&a[i].a,&a[i].b,s);
            if(s[0]==‘e‘)a[i].odd=0;
            else a[i].odd=1;
            if(a[i].a>a[i].b)swap(a[i].a,a[i].b);
            a[i].a--;
            b[++tot]=a[i].a;
            b[++tot]=a[i].b;
        }
        sort(b+1,b+1+tot);
        int nn=unique(b+1,b+1+tot)-b-1;
        tot=nn;
        init(nn);
        int flag=0;
        rep(i,1,m){
            int x=pos(a[i].a),y=pos(a[i].b);
            int odd=a[i].odd;
            int fx=find(x),fy=find(y);
            if(flag)continue;
            if(fx==fy){
                if((r[y]-r[x]+4&1)!=odd){
                    flag=i;
                }
            }else{
                link(fx,fy,x,y,odd);
            }
        }
        printf("%d\n",flag==0?m:flag-1);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/caturra/p/8724349.html

时间: 2024-11-14 13:13:49

POJ - 1733 离散化 并查集的相关文章

POJ 2492 (简单并查集) A Bug&#39;s Life

题意:有编号为1~n的虫子,开始假设这种昆虫是异性恋.然后已知xi 和 yi进行交配,根据已知情况分析能否推理出其中是否有同性恋 这道题和 POJ 1182 食物链 十分相似,不过在更新与父节点关系的时候要简单一些 sex数组保存的是与父节点的性别关系,如果与父节点是同性,则为0,否则是1 每次路径压缩的同时要更新sex[a] = (sex[a] + sex[temp]) % 2; 还有就是如果x 和 y 不在一个集合,两棵树进行合并的时候,考虑x px y py 四者之间的关系,有 paren

POJ - Colored Sticks - 并查集+字典树

这道题主要还是要判断是不是欧拉图 说白了就是能不能这幅图能不能用一笔画下来,那么就可以知道了,如果是一个环状的,说明奇数度就不存在,否则就只能用两个奇数度(起点终点)//我的理解这是 只需要用字典树将单词变为对应的一个数字,然后并查集操作就可以,需要维护一个度变量 #include<stdio.h> #include<string.h> int du[500010],p[500010]; int tot=1; struct tree { tree *next[30]; int id

poj 2513 欧拉回路+并查集判断是否联通+Trie树

http://poj.org/problem?id=2513 最初看到 第一感觉---map  一看250000的数据量 果断放弃 然后记得以前看过,trie代替map,尤其当数据量特别大的时候 学到了: 1.Trie代替map的思想,可以在单词结尾的tree[i][tk]  这个i作为字符串对应的int值 ,当然这个int值也可以用于建立并查集 2.接上,通过并查集判断,所有的点在同一个集合图就是联通的,否则不联通,注意tree[i][tk]>0 表示是单词结尾, x=Find(x);//这句

Poj 1733 Parity Game(离散化+并查集)

 题目大意:给出n个数字,m个区间内的数字和的奇偶性,询问从哪句话开始出现错误. 1.对于给定区间[l , r]的奇偶性,可以转化为[1. l-1]和[1, r]的奇偶性"关系",这样就可以用带权并查集来做了,权值为当前结点与根节点的奇偶性关系,每次查询如果l,r根结点相同,那么判断这句话是否正确,如果根节点不同,那么合并. 2.由于这道题数据量很大,但是查询只有m(m<=5000)所以要先将数据离散化.对于离散化,有两种方法,一种是考虑元素大小相对关系的,一种是不需要考虑元

POJ 1182 食物链 [并查集 带权并查集 开拓思路]

传送门 P - 食物链 Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 1182 Appoint description:  System Crawler  (2015-01-27) Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物

Poj(1703),种类并查集

题目链接:http://poj.org/problem?id=1703 已经不是第一次接触种类并查集了,直到今天才搞懂. 感谢红黑联盟,感谢杰哥!!! 每个节点只要关系确定,不管是不是同一个集合里面,都把他们放到一个集合里面,用一个rank[]数组记录他们与根节点的关系,比较神奇的地方有两处: 1.find函数里面,因为find是递归写的,不断往上找,不断更新rank[x](与根节点的关系),这个%k,也是很牛逼的,2种类型,标号只有01: 2.Union函数里面,更新rank[fy],rank

poj 2513 欧拉回路+并查集推断是否联通+Trie树

http://poj.org/problem? id=2513 最初看到 第一感觉---map  一看250000的数据量 果断放弃 然后记得曾经看过.trie取代map.尤其当数据量特别大的时候 学到了: 1.Trie取代map的思想,能够在单词结尾的tree[i][tk]  这个i作为字符串相应的int值 .当然这个int值也能够用于建立并查集 2.接上.通过并查集推断.全部的点在同一个集合图就是联通的,否则不联通,注意tree[i][tk]>0 表示是单词结尾. x=Find(x);//这

Poj(1182),种类并查集

题目链接:http://poj.org/problem?id=1182 再次熟练种类并查集,又积累点经验,和技巧,rank 0 2 1 先计算father[x] ,再更新rank[x]; #include <stdio.h> int father[50010]; int rank[50010]; int Find_Set (int x) { int tmp; if(x!=father[x]) { tmp = father[x]; father[x] = Find_Set(father[x]);

poj 1182 (关系并查集) 食物链

题目传送门:http://poj.org/problem?id=1182 这是一道关系型并查集的题,对于每个动物来说,只有三种情况:同类,吃与被吃: 所以可以用0,1,2三个数字代表三种情况,在使用并查集的时候再多加一个关系数组,初始时全部赋值为0 然后就是在进行并查集的每一步时加入关系的改变, 如果祖先节点相同,说明两者之间的关系已经出现,是已知的,判断两者关系之和与给的d-1是否相同 祖先节点不同,说明在此之前两者的关系还未知,就赋予关系 噢 对了 poj 上的这题要单组输入,多组会wa c