ural1003
2014-08-24 15:47
357 查看
哈哈哈哈 写了三个版本的,都阔以AC ,花了不少时间。。不过还是很开森的辣~~
题目大意:偶尔你跟朋友玩以下的游戏:你的朋友写下一串包含1和0的数串让你猜,你可以从中选择一个连续的子串(例如其中的第3到第5个数字)问他,该子串中包含了奇数个还是偶数个1,他会回答你的问题,然后你可以问其他子串,等等。
输入包含多组测试数据。 首行为整个数串的长度,小于或等于1000000000。第二行为一个正整数,表示问题及答案数,小于或等于5000。之后每行表示问题及答案。格式:2个整数(即子串的第一个及最后一个数位),答案为一个单词:'even'(偶),或'odd'(奇),即选择的子串中1的个数是奇数个,则答案为odd,否则为even。最后以-1结束。
输出x,x表示存在01数串满足前x个奇偶条件,但不满足第x+1个条件。。假如存在满足所有条件的01串,则输出的数字为问题总数。
代码1
介个是参考大神的,离散化用的map
代码3
和上面的几乎一样 就是这里自己离散化的。离散化用到二分,刚开始还傻傻不知道为毛还要用二分啊,后来突然间才知道,c[i]的数据量很大的,直接开数组hash[c[i]]=i离散化的 话数组会爆掉的...........
题目大意:偶尔你跟朋友玩以下的游戏:你的朋友写下一串包含1和0的数串让你猜,你可以从中选择一个连续的子串(例如其中的第3到第5个数字)问他,该子串中包含了奇数个还是偶数个1,他会回答你的问题,然后你可以问其他子串,等等。
输入包含多组测试数据。 首行为整个数串的长度,小于或等于1000000000。第二行为一个正整数,表示问题及答案数,小于或等于5000。之后每行表示问题及答案。格式:2个整数(即子串的第一个及最后一个数位),答案为一个单词:'even'(偶),或'odd'(奇),即选择的子串中1的个数是奇数个,则答案为odd,否则为even。最后以-1结束。
输出x,x表示存在01数串满足前x个奇偶条件,但不满足第x+1个条件。。假如存在满足所有条件的01串,则输出的数字为问题总数。
代码1
//如果已经知道序列 那么可以用线段树 但是现在不知道序列 // 拓展并查集 0 表示区间是偶数 个1, 1 表示区间是奇数个1 //fa[x]=y 表示 【x,y)连续区间 rank[x]表示该区间的奇偶性 #include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<cmath> #include<queue> using namespace std; int n; int fa[65521]; int rank[65521]; int a[65521],b[65521]; int c[65521*2]; char ch[65521][10]; int tot; void init() { for(int i=0;i<65521;i++) { fa[i]=i; rank[i]=0; } } int find(int x)//查找x的父亲是谁 { if(fa[x]!=x) { int father=find(fa[x]); rank[x]=(rank[x]+rank[fa[x]])%2; return fa[x]=father; } return x; } int Union(int x,int y,int d) { int tx=find(x); int ty=find(y); if(tx==ty) { if((rank[x]-rank[y]+2)%2!=d)return 0; else return 1; } else { fa[tx]=ty; rank[tx]=(rank[y]-rank[x]+d+2)%2; return 1; } } int bin(int x) { int low=0; int high=tot; while(low<=high) { int mid=(low+high)>>1; if(c[mid]==x)return mid; else if(c[mid]>x)high=mid-1; else low=mid+1; } return -1; } int main() { //freopen("q.in","r",stdin); int n,m; int i,tmp; while(scanf("%d",&n) && n!=-1) { init(); scanf("%d",&m); int res=0; tot=0; for(i=1;i<=m;i++) { scanf("%d%d%s",&a[i],&b[i],ch[i]);b[i]++; c[tot++]=a[i]; c[tot++]=b[i]; } sort(c,c+tot); tot=unique(c,c+tot)-c; for(i=1;i<=m;i++) { if(Union(bin(a[i]),bin(b[i]),(ch[i][0]=='o'))) { res++; } else break; } printf("%d\n",res); } }代码2
介个是参考大神的,离散化用的map
//换个思路 用前缀和的思路 两者是偶数表示是同一集合 奇数表示不是同一个集合 // 所以偶数0 奇数 1 总共分为集合1 集合0 两个集合 //所以 0 表示在一个集合 1 表示不再一个集合 //AC #include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<cmath> #include<queue> #include<map> using namespace std; #define maxn 10010 int fa[maxn],rank[maxn]; void init() { for(int i=0;i<10000;i++) { fa[i]=i; rank[i]=0; } } int find(int x) { if(fa[x]!=x) { int father=find(fa[x]); rank[x]=rank[x]^rank[fa[x]]; return fa[x]=father; } else return x; } bool unio(int a, int b, int d) { int x = find(a); int y = find(b); if(x == y) { return (rank[a] ^ rank[b]) ^ (!d) ; } else { fa[x] = y; rank[x] = (d + rank[b] - rank[a] + 4) % 2; return true; } } int main() { freopen("q.in","r",stdin); int n,m; int i,tmp; while(scanf("%d",&n) && n!=-1) { init(); scanf("%d",&m); map<int,int> mp; int a,b; char ch[10]; int res=0; int tot=0; int flag=0; for(i=0;i<m;i++) { scanf("%d%d%s",&a,&b,ch);a--; if(mp.find(a)==mp.end()) mp[a]=tot++; if(mp.find(b)==mp.end()) mp[b]=tot++; // cout<<mp[a]<<"*"<<mp[b]<<" "; if(unio(mp[a],mp[b],(ch[0]=='o'))) { //cout<<"9999"<<endl; if(!flag)res++; } else flag=1; } //cout<<endl; printf("%d\n",res); } }
代码3
和上面的几乎一样 就是这里自己离散化的。离散化用到二分,刚开始还傻傻不知道为毛还要用二分啊,后来突然间才知道,c[i]的数据量很大的,直接开数组hash[c[i]]=i离散化的 话数组会爆掉的...........
//换个思路 用前缀和的思路 两者是偶数表示是同一集合 奇数表示不是同一个集合 // 所以偶数0 奇数 1 总共分为集合1 集合0 两个集合 //所以 0 表示在一个集合 1 表示不再一个集合 // #include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<cmath> #include<queue> #include<map> using namespace std; #define maxn 10010 int fa[maxn],rank[maxn]; int a[maxn],b[maxn],c[maxn*2]; char ch[maxn][10]; int tot; void init() { for(int i=0;i<10000;i++) { fa[i]=i; rank[i]=0; } } int find(int x) { if(fa[x]!=x) { int father=find(fa[x]); rank[x]=rank[x]^rank[fa[x]]; return fa[x]=father; } else return x; } bool unio(int a, int b, int d) { int x = find(a); int y = find(b); if(x == y) { return (rank[a] ^ rank[b]) ^ (!d) ; } else { fa[x] = y; rank[x] = (d + rank[b] - rank[a] + 4) % 2; return true; } } int bin(int x) { int low=0; int high=tot; while(low<=high) { int mid=(low+high)>>1; if(c[mid]==x)return mid; else if(c[mid]>x)high=mid-1; else low=mid+1; } return -1; } int main() { //freopen("q.in","r",stdin); int n,m; int i,tmp; while(scanf("%d",&n) && n!=-1) { init(); scanf("%d",&m); int res=0; tot=0; for(i=1;i<=m;i++) { scanf("%d%d%s",&a[i],&b[i],ch[i]);a[i]--; c[tot++]=a[i]; c[tot++]=b[i]; } sort(c,c+tot); tot=unique(c,c+tot)-c; for(i=1;i<=m;i++) { if(unio(bin(a[i]),bin(b[i]),(ch[i][0]=='o'))) { res++; } else break; } printf("%d\n",res); } }
相关文章推荐
- URAL 1003 Parity
- Ural 1003 Parity(并查集)
- URAL 1003 Parity(并查集)
- URAL 1003 并查集
- Ural 1003 Parity
- Ural_1003 Parity(并查集)
- URAL1003 Parity
- ural 1003 Parity 并查集
- ural 1003. Parity(并查集)
- URAL 1003,1004
- PKU1733 URAL1003 Parity game
- poj1182和ural1003
- Ural(Timus) 1003 Parity
- URAL 1796 Amusement Park
- 递推DP URAL 1009 K-based Numbers
- URAL1017——DP——Staircases
- URAL1081——DP—— Binary Lexicographic Sequence
- TsinsenA1000,A1001,A1002,A1003,A1004,A1005,A1006,A1007,A1008,A1009,A1010水题记录
- Ural 1146 Maximum Sum
- ACM学习历程—BestCoder 2015百度之星资格赛1003 IP聚合(set容器)