POJ 1733 Party Game(加权并查集+hash)
来源:互联网 发布:处理器优化 编辑:程序博客网 时间:2024/06/08 16:49
题目链接:
POJ 1733 Party Game
题意:
有n个数字,每个数字非0即1,有m条语句,每条语句:l,r,even/odd,表示l到r区间上有奇/偶个1.
问最多前多少条语句是正确的?
分析:
和POJ 3038 How many answers are wrong? http://acm.hdu.edu.cn/showproblem.php?pid=3038 类似。
用val[i]表示从i到根节点路径上含有1的数量的奇偶性。在寻找根节点的同时更新路径上的val。
比较麻烦的是数据范围。n<=1000000000,而m<=5000.
①:可以用map来标记各个读入点的次序,相当于有个代号,在map里没读入的话就添加进map
在find()和mix()函数里相当于是对代号的操作,代号具有唯一性。
由于m<=5000,所以最多会读入10000个相异的数,那么对于pre数组和val数组都是可以接受的了。
②:hash思路。同样是代号的想法,把l(或r) mod maxn 值相同的归在一类,
用head数组的下标记录这类,head的数值表示最后一类的读入位置。和最短路里链式前向星的查找类似。
#include <iostream>#include <cstdio>#include <cmath>#include <cstring>#include <algorithm>#include <map>using namespace std;const int maxn=10010;int pre[maxn],val[maxn],n,m,l,r,w;char s[10];int find(int x){ if(pre[x]==x) return x; int tmp=find(pre[x]); val[x]=(val[x]+val[pre[x]])%2; return pre[x]=tmp;}int mix(int x,int y,int z)//语句正确,mix返回1,否则返回0。{ int fx=find(x); int fy=find(y); if(fx!=fy) { pre[fx]=fy; val[fx]=(val[y]-val[x]+z)%2; return 1; } else { if(abs(val[x]-val[y])%2==z) return 1; return 0; }}int main(){#ifdef LOCAL freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout);#endif while(~scanf("%d",&n)&&n) { for(int i=0;i<maxn;i++) { pre[i]=i; val[i]=0; } scanf("%d",&m); int ok=0; int ans=0; int index=0; map<int,int> mp; for(int i=1;i<=m;i++) { scanf("%d%d%s",&l,&r,s); if(s[0]=='e') w=0; else w=1; l--;//这样做就可以合并相邻的区间,例如:读入l=1,r=2和l=3,r=4 if(mp.find(l)==mp.end()) mp[l]=index++; //find()函数返回一个迭代器指向键值为key的元素,如果没找到就返回指向map尾部的迭代器 if(mp.find(r)==mp.end()) mp[r]=index++; //假设前x条语句是正确的,第x+1条是错的。那么前x次读入ok都为0,第x+1次读入由于ok=0,mix()返回0 //所以执行else语句,ok变为1,ans=i-1=(x+1)-1=x.从x+2开始由于ok=1,不会执行||后面的判断,恒continue. if(ok||mix(mp[l],mp[r],w)) continue; else ok=1; if(ok) ans=i-1; } if(ok==0) ans=m;//所有的语句都是正确的 printf("%d\n",ans); } return 0;}
#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>#include <cstring>#include <map>using namespace std;const int maxn=5050;int n,m,l,r,w,tot;int head[maxn],val[maxn],pre[maxn];char s[10];struct Point{ int value,next;}point[maxn];int hash(int n){ int m=n%maxn; for(int i=head[m];i!=-1;i=point[i].next) if(point[i].value==n) return i; point[tot].value=n; point[tot].next=head[m]; head[m]=tot++; return (tot-1);}int find(int x){ if(pre[x]==x) return x; int tmp=find(pre[x]); val[x]=(val[x]+val[pre[x]])%2; return pre[x]=tmp;}int mix(int x,int y,int z){ int fx=find(x); int fy=find(y); if(fx!=fy) { pre[fx]=fy; val[fx]=(val[y]-val[x]+z)%2; return 1; } else { if(abs(val[x]-val[y])%2==z) return 1; return 0; }}int main(){#ifdef LOCAL freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout);#endif while(~scanf("%d",&n)&&n) { memset(head,-1,sizeof(head)); memset(val,0,sizeof(val)); for(int i=0;i<maxn;i++) pre[i]=i; tot=0; scanf("%d",&m); int ans=m; int ok=0; for(int i=1;i<=m;i++) { scanf("%d%d%s",&l,&r,s); l=hash(l-1); r=hash(r); if(s[0]=='e') w=0; else w=1; if(ok||mix(l,r,w)) continue; else ok=1; if(ok) ans=i-1; } printf("%d\n",ans); } return 0;}
0 0
- POJ 1733 Party Game(加权并查集+hash)
- POJ 1733 parity game (hash离散+并查集)
- POJ-1988 Cube Stacking (加权并查集)
- POJ 1182 食物链(加权并查集)
- POJ 1984 Navigation Nightmare(加权并查集)
- POJ 2912 Rochambeau(枚举+加权并查集)
- POJ 1182 食物链 加权并查集
- POJ[1182]食物链 加权并查集
- POJ 1733 Parity game hash离散化+带权并查集
- poj Parity game(带权并查集)(hash离散化)
- POJ 1733 Parity game(并查集)
- POJ 1733 Parity game (并查集)
- 【POJ】1733 Parity game 并查集
- poj-1733 Parity game 并查集
- [POJ 1733]Parity game[并查集]
- POJ 1733 Parity game(并查集)
- poj 1733 Parity game (并查集+向量偏移)
- POJ - 1733 Parity game (带权并查集)
- Broadcast广播内部机制
- 利用矩阵计算提升推荐系统的速度
- python3 字符编码处理
- 动态规划之整齐打印
- CentOS 下FTP服务器(vsftpd)的安装
- POJ 1733 Party Game(加权并查集+hash)
- xcode在真机调试的时候出现"The identity used to sign the executable is no longer valid"
- CAShapeLayer + UIBezierPath结合动画效果
- UIWebView的屏幕旋转如何适配
- session保存技巧
- 比较汉字的方法
- 带表情符号的自定义键盘
- 安卓动画android:interpolator
- ActiveMQ持久化消息的三种方式