2012 Multi-University Training Contest 4
2012-08-14 11:44
351 查看
1004 线性查找 O(n^3)
题意:有五个集合,每个集合中最多有200个数,从每个集合中选出一个数判断这五个数的和能否是零。
思路:如果直接暴力的话复杂度是O(n^5) TLE , 在网上看到一种所谓的线性查找的方法,刚开始跟这个思路差不多,但是还是TLE。。
把第一个集合的第二个集合的所有和的情况组成新的s1,第三个和第四个集合所有和的情况组成s2,然后对s1和s2分别排序 O(n^2 + n^n + nlgn + nlgn)
然后枚举最后一个集合的元素,对每一个元素,s1和s2一个从小枚举,一个从大枚举,如果s1[i] + s2[j] + tmp > 0 说明大的太大,j--; 如果小于零那么小的太小i++;这样最坏也就是2*n^n^n O(n^3)
参考于楼长:/article/6138334.html
1006 容斥原理
因为不想浪费那么最理想的情况就是s1∪s2∪s3...∪sn , si为在pi概率下要买的方便面袋数。
|A1∪A2∪...∪An| = Σ|Ai| - Σi~nΣj>i|Ai∩Aj| + (-1)^(n-1)|A1∩A2∩...∩An|
所以官方这个公式也就很裸了
还有就是求"C(n,2) C(n,3) ... C(n.n)" 是用dfs实现的
1009 线段树
题意:给出两个字符串,更新操作是更新1 a i c 代表把第a个string的第i号字符更新成字符c,询问操作是2 i代表从第一个字符串i开始去逐位匹配第二个字符串输出第一个失配的位置。
思路:很明显的线段树。。。有思路,还是搞不定这个线段树啊。。搓!后来看了下别人的思路搞了搞,可是有些细节还是处理不好。。。
主要参考:/article/6726307.html
主要就是不明白一点,在build和update 于PushUP结合的时候更新已经完成,询问的时候直接找cnt的值就完了呗,但是还是要判断在左区间的公共子串值是不是填满了左区间长度。。。不加就WA。。。 有点疑惑
题意:有五个集合,每个集合中最多有200个数,从每个集合中选出一个数判断这五个数的和能否是零。
思路:如果直接暴力的话复杂度是O(n^5) TLE , 在网上看到一种所谓的线性查找的方法,刚开始跟这个思路差不多,但是还是TLE。。
把第一个集合的第二个集合的所有和的情况组成新的s1,第三个和第四个集合所有和的情况组成s2,然后对s1和s2分别排序 O(n^2 + n^n + nlgn + nlgn)
然后枚举最后一个集合的元素,对每一个元素,s1和s2一个从小枚举,一个从大枚举,如果s1[i] + s2[j] + tmp > 0 说明大的太大,j--; 如果小于零那么小的太小i++;这样最坏也就是2*n^n^n O(n^3)
参考于楼长:/article/6138334.html
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; //typedef long long ll; const int maxn = 210; __int64 s1[maxn*maxn] , s2[maxn*maxn]; __int64 a[maxn] , b[maxn] , c[maxn] , d[maxn] , e[maxn]; int main() { int T , cas = 1; int n , i , j; scanf("%d",&T); while(T--) { memset(s1 , 0 , sizeof(s1)); memset(s2 , 0 , sizeof(s2)); scanf("%d",&n); for(i = 1 ; i <= n ; i ++) scanf("%I64d",&a[i]); for(i = 1 ; i <= n ; i ++) scanf("%I64d",&b[i]); for(i = 1 ; i <= n ; i ++) scanf("%I64d",&c[i]); for(i = 1 ; i <= n ; i ++) scanf("%I64d",&d[i]); for(i = 1 ; i <= n ; i ++) scanf("%I64d",&e[i]); int k = 0; for(i = 1 ; i <= n ; i ++) for(j = 1 ; j <= n ; j ++) s1[k++] = a[i] + b[j]; int t = 0; for(i = 1 ; i <= n ; i ++) for(j = 1 ; j <= n ; j ++) s2[t++] = c[i] + d[j]; sort(s1 , s1 + k); sort(s2 , s2 + t); sort(&e[1], e + n + 1); int flag = 0; int f; for(f = 1 ; f <= n ; f ++) { __int64 tmp = e[f]; //没有声明__in64 WA了好几次 i = 0 , j = t - 1; while(i < k && j >= 0) { if(s1[i] + s2[j] + tmp == 0 ) { flag = 1; break; } if(s1[i] + s2[j] + tmp > 0) j--; else i ++; } if(flag) break; } if(flag) printf("Yes\n"); else printf("No\n"); } }
1006 容斥原理
因为不想浪费那么最理想的情况就是s1∪s2∪s3...∪sn , si为在pi概率下要买的方便面袋数。
|A1∪A2∪...∪An| = Σ|Ai| - Σi~nΣj>i|Ai∩Aj| + (-1)^(n-1)|A1∩A2∩...∩An|
所以官方这个公式也就很裸了
还有就是求"C(n,2) C(n,3) ... C(n.n)" 是用dfs实现的
#include<iostream> #include<cstdio> #include<cstring> using namespace std; double s , P[25]; int k , n; void dfs(int cnt , double p , int i) { if(cnt == k) { s += 1.0/p; return; } for(int j = i ; j <= n ; j ++) { dfs(cnt + 1 , p + P[j] , j + 1); } } int main() { int i; while(~scanf("%d",&n)) { double sum = 0; for(i = 1 ; i <= n ; i ++) { scanf("%lf",&P[i]); sum += 1.0/P[i]; } for(i = 2 ; i <= n ; i ++) { k = i; s = 0; dfs(0 , 0 , 1); if(i%2==0) s = (-1)*s; sum += s; } printf("%lf\n",sum); } }
1009 线段树
题意:给出两个字符串,更新操作是更新1 a i c 代表把第a个string的第i号字符更新成字符c,询问操作是2 i代表从第一个字符串i开始去逐位匹配第二个字符串输出第一个失配的位置。
思路:很明显的线段树。。。有思路,还是搞不定这个线段树啊。。搓!后来看了下别人的思路搞了搞,可是有些细节还是处理不好。。。
主要参考:/article/6726307.html
主要就是不明白一点,在build和update 于PushUP结合的时候更新已经完成,询问的时候直接找cnt的值就完了呗,但是还是要判断在左区间的公共子串值是不是填满了左区间长度。。。不加就WA。。。 有点疑惑
#include<iostream> #include<cstdio> #include<cstring> using namespace std; #define lson l , m , rt<<1 #define rson m + 1 , r , rt<<1|1 const int maxn = 1000010; int cnt[maxn<<2]; // 以区间左端点为起点的公共子串长度 char s1[maxn] , s2[maxn]; void PushUP(int rt , int m , int l) { //printf("Up %d\n",rt); if(cnt[rt<<1] == (m - l + 1)) cnt[rt] = cnt[rt<<1] + cnt[rt<<1|1]; else cnt[rt] = cnt[rt<<1]; } void build(int l , int r , int rt) { if(l == r) { if(s1[l] == s2[l]) { cnt[rt] = 1; } else cnt[rt] = 0; return; } int m = (l + r) >> 1; build(lson); build(rson); PushUP(rt , m , l); } void Update(int i , int l , int r , int rt) { if(l == r) { if(s1[l] == s2[l]) cnt[rt] = 1; else cnt[rt] = 0; return; } int m = (l + r) >> 1; if(i <= m) Update(i , lson); else Update(i , rson); PushUP(rt , m , l); } int Query(int i , int l , int r , int rt) { if(i == l) return cnt[rt]; int m = (l + r) >> 1; int ans; if(i <= m) { ans = Query(i , lson); if(ans == m - i + 1) ans += cnt[rt<<1|1]; //感觉不用加 但是去掉就WA } else ans = Query(i , rson); return ans; } int main() { int T , cas = 1; scanf("%d",&T); while(T--) { scanf("%s %s",s1,s2); int Q; int l1 , l2; l1 = strlen(s1); l2 = strlen(s2); build(0 , l1 - 1, 1); printf("Case %d:\n",cas++); scanf("%d",&Q); while(Q--) { int t , i , j; char c; scanf("%d",&t); if(t == 2) { scanf("%d",&i); if(i >= l1) printf("0\n"); else printf("%d\n",Query(i , 0 , l1 - 1, 1)); } if(t == 1) { scanf("%d %d %c",&i,&j,&c); if(i == 1) s1[j] = c; else s2[j] = c; Update(j , 0 , l1 - 1 , 1); } } } }
相关文章推荐
- hdu4323-Magic Number-2012 Multi-University Training Contest 3题解
- hdu 4365 Palindrome graph (规律题 + 快速幂取模 2012 Multi-University Training Contest 7 )
- 2012 Multi-University Training Contest 8
- 2012 Multi-University Training Contest 2
- 2012 Multi-University Training Contest 4
- 2012 Multi-University Training Contest 5-1001 hdu4340
- 2012 Multi-University Training Contest 5[hdu4340~4349]
- 2012 Multi-University Training Contest 7
- 2012 Multi-University Training Contest 7-1001 hdu4360 As long as Binbin loves Sangsang
- 2012 Multi-University Training Contest 8[hdu4370~4379]
- 2012 Multi-University Training Contest 9__Farmer Greedy和Quadrilateral
- hdu 4348 To the moon(线段树成段更新) 2012 Multi-University Training Contest 5
- 2012 Multi-University Training Contest 7-1003 hdu4362 Dragon Ball
- 2012 Multi-University Training Contest 8
- 2012 Multi-University Training Contest 6-1009 hdu4358 Boring counting
- 2012 Multi-University Training Contest 1 Divide Chocolate(递推)
- 2012 Multi-University Training Contest 2
- 2012 Multi-University Training Contest 3[hdu4320~4330]
- 2012 Multi-University Training Contest 3
- 2012 Multi-University Training Contest 4-1007 hdu4337 King Arthur's Knights