Codeforces Round #267 (Div. 2)
来源:互联网 发布:淘宝网儿童内衣 编辑:程序博客网 时间:2024/06/09 18:54
昨晚又打了场div2,最近div2场怎么这么多……
467A - George and Accommodation
不能更水……
#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<stack>#include<set>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-8#define pi acos(-1.0)using namespace std;typedef long long ll;int main(){// freopen("in.txt","r",stdin);// freopen("out.txt","w",stdout); int n,p,q; int ans = 0; scanf("%d",&n); for(int i = 0;i < n;++i) { scanf("%d%d",&p,&q); if(p + 2 <= q) ans++; } printf("%d\n",ans); return 0;}
467B - Fedor and New Game
给出m+1个数,求第m+1个数和前面所有的数有多少个数,二进制表示下位数不同的数量 <= k。异或一下然后统计有多少个1即可,非常水。。。
#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<stack>#include<set>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-8#define pi acos(-1.0)using namespace std;typedef long long ll;const int maxn = 1000 + 10;int x[maxn];int getbit(int x){ int cnt = 0; while(x) { cnt++; x = x & (x-1); } return cnt;}int main(){// freopen("in.txt","r",stdin);// freopen("out.txt","w",stdout); int n,m,k; scanf("%d%d%d",&n,&m,&k); for(int i = 0;i <= m;++i) scanf("%d",&x[i]); int ans = 0; for(int i = 0;i < m;++i) { int y = x[i]^x[m]; if(getbit(y) <= k) ans++; } printf("%d\n",ans); return 0;}
467C - George and Job
从一个序列中选k个长度为m的序列,并且不能相交,求k个序列的和的最大值。dp就行了,dp[i][j]表示最后一个选的序列的结尾是i,此时选了j个的最大值。dp[i][j] = max(dp[k][j-1] + sum[i] - sum[i-m]),0 <= k <= i - m,用个数组保存一下最大值即可。开始用了二维数组保存最大值了,但是MLE了两发,太坑了,注意一下dp的顺序就可以用一维的数组来维护了。
#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<stack>#include<set>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-8#define pi acos(-1.0)using namespace std;typedef long long ll;const int maxn = 5000 + 5;int a[maxn];ll sum[maxn],dp[maxn][maxn],maxv[maxn];int main(){// freopen("in.txt","r",stdin);// freopen("out.txt","w",stdout); int n,m,k; scanf("%d%d%d",&n,&m,&k); for(int i = 1;i <= n;++i) scanf("%d",&a[i]); sum[0] = 0; for(int i = 1;i <= n;++i) sum[i] = sum[i-1] + a[i]; memset(dp,0xff,sizeof(dp)); memset(maxv,0,sizeof(maxv)); dp[0][0] = 0; for(int j = 1;j <= k;++j) { for(int i = 1;i <= n;++i) { if(i - m >= 0) { dp[i][j] = max(dp[i][j],maxv[i-m] + sum[i] - sum[i-m]); } } for(int i = 1;i <= n;++i) maxv[i] = max(maxv[i-1],dp[i][j]); } ll ans = 0; for(int i = 1;i <= n;++i) if(dp[i][k] != -1) ans = max(ans,dp[i][k]); printf("%I64d\n",ans); return 0;}
467D - Fedor and Essay
给出一个文章,由m个单词组成,再给出n对同义词a,b,表示a能被b替换(反之不成立),可以将给出的单词用同义词替换,要求最后文章中的字母r的数量最少,在这个前提下让文章所包含的字符数最少,单词不区分大小写。
比赛时没写完,太伤心。。。其实要用r尽量少并且长度小的单词尽量去替换给出的单词,如果对于每个单词预处理出来哪个单词替换它最优,那么就可以直接得出答案。可以考虑同义词中的最优的单词,如果从这个单词出发,那么能替换成这个单词的就要尽量替换成它,然后标记掉,标记掉的一定是最优的,那么接下来只需要寻找下一没标记的单词接着搜就好了。
#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<stack>#include<set>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-8#define pi acos(-1.0)using namespace std;typedef long long ll;const int maxn = 600000 + 10;map<string,int>mp;string s1,s2,str[100000 + 10];vector<int>G[maxn];int rnt[maxn],len[maxn],best[maxn];bool vis[maxn];struct Node{ int a,b,id; Node(int a = 0,int b = 0,int id = 0):a(a),b(b),id(id){} bool operator < (const Node & x) const { return (a == x.a && b > x.b) || (a > x.a); }};priority_queue<Node>q;queue<int>que;inline void cal(int id,string s){ len[id] = s.length(); rnt[id] = 0; for(int i = 0;i < len[id];++i) if(s[i] == 'r') rnt[id]++;}int main(){// freopen("in.txt","r",stdin);// freopen("out.txt","w",stdout); int m,n,cnt = 0; cin>>m; for(int i = 1;i <= m;++i) { cin>>s1; int l = s1.length(); for(int j = 0;j < l;++j) if(s1[j] >= 'A' && s1[j] <= 'Z') s1[j] += 'a' - 'A'; str[i] = s1; if(mp.find(s1) == mp.end()) { cnt++; mp[s1] = cnt; cal(cnt,s1); } } cin>>n; int a,b; for(int i = 0;i < n;++i) { cin>>s1>>s2; int l = s1.length(); for(int j = 0;j < l;++j) if(s1[j] >= 'A' && s1[j] <= 'Z') s1[j] += 'a' - 'A'; l = s2.length(); for(int j = 0;j < l;++j) if(s2[j] >= 'A' && s2[j] <= 'Z') s2[j] += 'a' - 'A'; if(mp.find(s1) == mp.end()) { cnt++; mp[s1] = cnt; cal(cnt,s1); } if(mp.find(s2) == mp.end()) { cnt++; mp[s2] = cnt; cal(cnt,s2); } a = mp[s1]; q.push(Node(rnt[a],len[a],a)); b = mp[s2]; q.push(Node(rnt[b],len[b],b)); G[b].push_back(a); } for(int i = 1;i <= cnt;++i) best[i] = i; Node node; while(!q.empty()) { node = q.top();q.pop(); if(vis[node.id]) continue; que.push(node.id); while(!que.empty()) { int u = que.front();que.pop(); if(vis[u]) continue; vis[u] = true; for(int i = 0;i < (int)G[u].size();++i) { int v = G[u][i]; if(vis[v]) continue; best[v] = node.id; que.push(v); } } } ll ans1 = 0,ans2 = 0; for(int i = 1;i <= m;++i) { int id = mp[str[i]]; if(rnt[best[id]] < rnt[id] || (rnt[best[id]] == rnt[id] && len[best[id]] < len[id])) { id = best[id]; } ans1 += rnt[id]; ans2 += len[id]; } cout<<ans1<<" "<<ans2<<endl; return 0;}
467E - Alex and Complicated Task
感觉这题还挺简单的,早知道可以先做做这题 。。。。题意大概就是要在一个序列中取出一个尽量长的子序列,满足给定的要求……
从给定的要求中可以发现,要求的数组是每四个一组的,并且第1个和第3个相等,第2个和第4个相等,那么就有个贪心的过程,我们要构造这个序列,那么尽可能要取原序列中靠前的数字组成,这样才可能令序列尽量长。那么问题就变成了,当前原序列中s之前的都取完了,当前的位置是i,从这个区间中是否能选出满足要求的四个数,可以发现,如果这个区间有答案,那么第i个数一定要选,如果第i个数不选,那么说明s ~ i-1中就可以得到这4个数,那么在i-1的时候已经算出来了。
想到这里,大概就有些思路了,我们发现num[i]这个数在区间中不会超过4个,因为4个相同的数字一定能
构造出一个解,预处理一个数组pre[i],表示与第i个数字相同并在它左边的第一个位置,那么就可以枚举一下第二个数的位置j了,接下来的问题就是查询s ~ j-1 和 j + 1~ i -1 中是否有相同的数字,这个可以用线段树搞一下,对于一个位置i,线段树的值是pre[i],那么就是要查询区间[j+1,i - 1]中的最小值是否小于j,如果小于j,那么就有解,注意为了保证查询的值大于等于s,在查询开始之前把小于s的值都删掉。
#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<stack>#include<set>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-8#define pi acos(-1.0)using namespace std;typedef long long ll;const int maxn = 500000 + 10;struct Node{ int a,b; Node(int a = 0,int b = 0):a(a),b(b){} bool operator < (const Node & x) const { return a > x.a; }};int num[maxn],a[maxn],b[maxn],pre[maxn],last[maxn],ans[maxn],tot;int minv[maxn<<2],mpos[maxn<<2];priority_queue<Node>q;inline void PushUp(int rt){ if(minv[rt<<1] < minv[rt<<1|1]) { minv[rt] = minv[rt<<1]; mpos[rt] = mpos[rt<<1]; } else { minv[rt] = minv[rt<<1|1]; mpos[rt] = mpos[rt<<1|1]; }}void build(int l,int r,int rt){ minv[rt] = inf; mpos[rt] = l; if(l == r) return ; int m = (l + r)>>1; build(l,m,rt<<1); build(m+1,r,rt<<1|1);}void Update(int p,int l,int r,int rt,int v){ if(l == r) { minv[rt] = v; return ; } int m = (l + r)>>1; if(m >= p) Update(p,l,m,rt<<1,v); else Update(p,m+1,r,rt<<1|1,v); PushUp(rt);}int Query(int L,int R,int l,int r,int rt,int & p){ if(l >= L && r <= R) { p = mpos[rt]; return minv[rt]; } int m = (l + r)>>1; if(m >= R) return Query(L,R,l,m,rt<<1,p); else if(m < L) return Query(L,R,m+1,r,rt<<1|1,p); else { int r1,r2,p1,p2; r1 = Query(L,R,l,m,rt<<1,p1); r2 = Query(L,R,m+1,r,rt<<1|1,p2); if(r2 < r1) r1 = r2,p1 = p2; p = p1; return r1; }}int main(){// freopen("in.txt","r",stdin);// freopen("out.txt","w",stdout); int n; scanf("%d",&n); for(int i = 1;i <= n;++i) { scanf("%d",&a[i]); num[i] = b[i] = a[i]; } sort(b + 1,b + n + 1); int N = unique(b + 1, b + n + 1) - (b+1); for(int i = 1;i <= n;++i) a[i] = lower_bound(b + 1,b + N + 1,a[i]) - b; memset(last,0xff,sizeof(last)); for(int i = 1;i <= n;++i) { if(last[a[i]] == -1) pre[i] = 0; else pre[i] = last[a[i]]; last[a[i]] = i; } build(1,n,1); tot = 0; Node node; int s = 1; for(int i = 1;i <= n;++i) { while(!q.empty()) { node = q.top(); if(node.a < s) { Update(node.b,1,n,1,inf); q.pop(); } else break; } int cnt = 0; int j = i; while(j >= s) { j = pre[j]; cnt++; } if(cnt > 3) { ans[tot++] = num[i]; ans[tot++] = num[i]; ans[tot++] = num[i]; ans[tot++] = num[i]; s = i + 1; } else { j = pre[i]; while(j > s) { int pnow,plast; if(j + 1 <= i - 1) { plast = Query(j + 1,i - 1,1,n,1,pnow); if(plast < j) { ans[tot++] = num[plast]; ans[tot++] = num[j]; ans[tot++] = num[pnow]; ans[tot++] = num[i]; s = i + 1; break; } } j = pre[j]; } } Update(i,1,n,1,pre[i]); q.push(Node(pre[i],i)); } printf("%d\n",tot); for(int i = 0;i < tot;++i) { if(i) putchar(' '); printf("%d",ans[i]); } puts(""); return 0;}
- Codeforces Round #267 (Div. 2)
- Codeforces Round #267 (Div. 2)
- 【CodeForces】Codeforces Round #267 (Div. 2)
- Codeforces Round #267 (Div. 2) 解题报告
- Codeforces Round #267 (Div. 2) A
- Codeforces Round #267 (Div. 2) B
- Codeforces Round #267 (Div. 2) C
- Codeforces Round #267 (Div. 2) C
- Codeforces Round #267 (Div. 2) B
- 【索引】Codeforces Round #267 (Div. 2)
- Codeforces Round #267 (Div. 2) D
- Codeforces Round #102 (Div. 2)
- Codeforces Round #103 (Div. 2)
- Codeforces Round #103 (Div. 2)
- Codeforces Round #104 (Div. 2)
- Codeforces Round #105 (Div. 2)
- Codeforces Round #105 (Div. 2)
- Codeforces Round #107 (Div. 2)
- 系统运行慢的原因
- Auto Layout
- Oracle E-Business Suite网络测试(Network Test) Form
- springmvc笔记之 -- 常见注解的意思
- eclipse运行maven的内存溢出
- Codeforces Round #267 (Div. 2)
- VS2005 + VSS2005 实现团队开发
- C++ primer 第五版 中文版 练习 11.8 个人code
- Minimum_Window_Substring两种方法求解
- IOS 6 自动布局 入门-1
- IOS 6 自动布局 入门-2
- Java正则表达式入门
- VSS 2005 配置(含录像)
- How do I quickly switch between workspaces in unity? up vote 41 down vote favorite 8 I'm using U