Codeforces Round #367 (Div. 2) 题解

来源:互联网 发布:淘宝牛仔裤品牌排行榜 编辑:程序博客网 时间:2024/05/10 16:16

题目链接:http://codeforces.com/contest/706


感想:唯一一次前四道题全部都有思路,而且能保证正确的一次CF。但是最后却只A了前两道水题,最后没能来得及写后两道题。也许是太晚了,脑袋不太清醒吧!后面才想到后两题的做法。回想一下,从18分钟写完B后,就开始打酱油到比赛末,最后只A两题,就愤愤不平。555555!


A.思路:水题。直接将各个点与源点比较算时间,求出最小值即可。详见代码。

#include <bits/stdc++.h>using namespace std;double a, b;int n;int main(){//ios::sync_with_stdio(false);//cin.tie(0);cin >> a >> b >> n;double ans = INT_MAX;double x, y, v;while (n--){cin >> x >> y >> v;ans = min(ans, sqrt((x-a)*(x-a)+(y-b)*(y-b))/v);}printf("%.8f\n", ans);return 0;}

B.思路:排序后二分查找或者树状数组可以解决。这里用的是树状数组,树状数组下标是输入的数,存储的是某区间小于等于给定数的个数。详见代码。注意:树状数组的写法,要注意询问时,给出的数可能大于最大下标。

#include <bits/stdc++.h>using namespace std;const int maxn = 100005;int sum[maxn];int n, q;int lowbit(int x){return x&(-x);}void add(int p){while (p < maxn){++sum[p];p += lowbit(p);}}int query(int p){int ans = 0;while (p > 0){ans += sum[p];p -= lowbit(p);}return ans;}int main(){ios::sync_with_stdio(false);cin.tie(0);cin >> n;int num;while (n--){cin >> num;add(num);}cin >> q;while (q--){cin >> num;if (num >= maxn)num = maxn-1;cout << query(num) << endl;}return 0;}

C.思路:一开始准备枚举一遍后,得出结果。后来发现有问题,得到的结果明显不对。后来再仔细分析一下,发现是一道简单DP题,状态转移比较简单,不多解释。详见代码。

#include <bits/stdc++.h>using namespace std;typedef long long ll;const int maxn = 100005;const ll inf = 0x3f3f3f3f3f3f3f3fll;ll dp[maxn][2];int cost[maxn];string s[maxn], t[maxn];int n;int main(){ios::sync_with_stdio(false);cin.tie(0);cin >> n;for (int i=1; i<=n; ++i)cin >> cost[i];for (int i=1; i<=n; ++i){cin >> s[i];t[i] = s[i];reverse(t[i].begin(), t[i].end());dp[i][0] = dp[i][1] = inf;}dp[1][0] = 0;dp[1][1] = cost[1];for (int i=2; i<=n; ++i){if (s[i] >= s[i-1])dp[i][0] = dp[i-1][0];if (s[i] >= t[i-1])dp[i][0] = min(dp[i][0], dp[i-1][1]);if (t[i] >= s[i-1])dp[i][1] = dp[i-1][0]+cost[i];if (t[i] >= t[i-1])dp[i][1] = min(dp[i][1], dp[i-1][1]+cost[i]);}ll ans = min(dp[n][0], dp[n][1]);cout << (ans==inf ? -1 : ans) << endl;return 0;}

D.思路:一道字典树的题。将要插入的数的二进制位倒着建树(为什么?因为异或时高位尽量大,结果才尽量大),即高位在深度低的节点上。用一个数组记录经过各个节点的数的个数,插入时,每经过一个点,将节点的这个值加一,删除时,则减一。查找时,当前节点的这个值大于0,说明有数经过。对于要查找的这个数的高位,如果是1,要使异或值尽量大,那么就要往0的地方走,反之,往1的地方走,实在没办法走,只有按原路径走啦。详见代码。注意:0永远在树中。

#include <bits/stdc++.h>using namespace std;const int maxn = 3000005;int child[maxn][2], val[maxn];int q, sz=1;string op;void _insert(int x){int pos = 0;for (int i=29; i>=0; --i){int id = (x>>i)&1;if (!child[pos][id])child[pos][id] = sz++;pos = child[pos][id];++val[pos];}}void _delete(int x){int pos = 0;for (int i=29; i>=0; --i){int id = (x>>i)&1;pos = child[pos][id];--val[pos];}}int query(int x){int ans=0, pos=0;for (int i=29; i>=0; --i){int id = (x>>i)&1;if (id == 1){if (child[pos][0] && val[child[pos][0]]){ans += 1<<i;pos = child[pos][0];}elsepos = child[pos][1];}else{if (child[pos][1] && val[child[pos][1]]){ans += 1<<i;pos = child[pos][1];}elsepos = child[pos][0];}}return ans;}int main(){ios::sync_with_stdio(false);cin.tie(0);cin >> q;int num;_insert(0);while (q--){cin >> op >> num;if (op[0] == '+')_insert(num);else if (op[0] == '-')_delete(num);elsecout << query(num) << endl;}return 0;}


1 0
原创粉丝点击