http://codeforces.com/contest/1282
坚持下去谁也不知道结果是什么,但不坚持我肯定会后悔的。
这场比赛自闭了,对我极其不友好,读不懂,读懂了又做不来。
题意:给一个区间[a,b],以及一个基站c,以及信号覆盖范围半径r,一个人以单位速度从a到b运动,问过程中有多少时间不再基站信号范围内。
做法:直接模拟即可,求出信号的区间,与原来的区间相比即可。
//#include
//#include
//#include
//#include
//#include
//#include
#include "bits/stdc++.h"
using namespace std;
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
//#define ls(x) tr[x].ls
//#define rs(x) tr[x].rs
//#define lowbit(x) x&-x
const int inf = 0x3f3f3f3f;
const int maxn = 200000 + 10;
typedef long long ll;
void solve() {
ll a, b, c, r;
cin >> a >> b >> c >> r;
if (a > b) swap(a, b);
int la = c - r;
int lb = c + r;
ll ans = 0;
if (la <= a && lb >= b) {
cout << 0 << endl;
return;
}
if (la >= a && la <= b) ans += la - a;
if (lb <= b && lb >= a) ans += b - lb;
if (ans == 0) ans = b - a;
cout << ans << endl;
}
int main() {
int T;
cin >> T;
while (T--) {
solve();
}
return 0;
}
这道题自闭的开始。题目又长,英文又不好,不想看,他们口嗨了一句,k个优惠只能用一次。我居然当真了,然后WA了,后来又看见必须要有k个才能用。。。然后就写了假算法,最后知道题意,想了个dp,想太复杂了放弃了,跟着它们乱搞了一个二分答案过去了?????…
题意:给你n个物品的价值,以及你拥有的钱,如果你能买任意k个中最贵的那一个,那么另外k-1个免费获得。问最多能得到多少个。
做法:其实不复杂的,首先排一个序,我们想象一个状态d[i]表示前i个都买了最少花费。
那么就可以这样递推 d [ i ] = a [ i ] + ( i > = k ) ? s [ i − k ] : s [ i − 1 ] d[i]=a[i]+(i>=k)?s[i-k]:s[i-1] d[i]=a[i]+(i>=k)?s[i−k]:s[i−1]
然后遍历答案就可以了,因为假设你最多能买x个,那么这x个一定是前x个。
//#include
//#include
//#include
//#include
//#include
//#include
#include "bits/stdc++.h"
using namespace std;
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
//#define ls(x) tr[x].ls
//#define rs(x) tr[x].rs
//#define lowbit(x) x&-x
const int inf = 0x3f3f3f3f;
const int maxn = 200000 + 10;
typedef long long ll;
ll n, p, k, a[maxn], s[maxn];
void solve() {
cin >> n >> p >> k;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
sort(a + 1, a + n + 1);
int ans = 0;
s[0] = 0;
for (int i = 1; i <= n; i++) {
if (i < k) s[i] = s[i - 1] + a[i];
else s[i] = s[i - k] + a[i];
if (s[i] <= p) ans = i;
}
cout << ans << endl;
}
int main() {
int T;
cin >> T;
while (T--) {
solve();
}
return 0;
}
这道题原谅我英语水平不好。照着翻译看了半天才看懂。
题意:给出题目中所说的人解决一个困难和简单问题所需要的时间,以及总时间和题目的数量以及难度。最后给出每个题目变成"强制性"的时间,如果到了题目变成了强制性没有完成任何一道强制性题目,都会得零分,当然你可以提前离场。问最多能得多少分,一个题目一分。
做法:按照变成强制性的时间从小到大进行排序,记录先前变成强制性题目的数量,并与ti-1进行比较如果过大就零分,过小就优先解决后面的简单的问题,然后更新答案。这样贪心即可。
//#include
//#include
//#include
//#include
//#include
//#include
#include "bits/stdc++.h"
using namespace std;
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
//#define ls(x) tr[x].ls
//#define rs(x) tr[x].rs
//#define lowbit(x) x&-x
const int inf = 0x3f3f3f3f;
const int maxn = 200000 + 10;
typedef long long ll;
struct node {
int f;
ll t;
} p[maxn];
bool cmp(node a, node b) { return a.t < b.t; }
int n;
ll t, a, b;
void solve() {
cin >> n >> t >> a >> b;
int cnta = 0, cntb = 0;
for (int i = 1; i <= n; i++) {
cin >> p[i].f;
if (p[i].f) cntb++;
else cnta++;
}
for (int i = 1; i <= n; i++) cin >> p[i].t;
sort(p + 1, p + n + 1, cmp);
p[n + 1].t = t + 1;
ll ans = 0, c1 = 0, c2 = 0;
for (int i = 1; i <= n + 1; i++) {
ll tmp = c1 * a + c2 * b;
ll time = p[i].t - 1 - tmp;
if (time >= 0) {
ll ta = min(time / a, cnta - c1);
time -= ta * a;
ll tb = min(time / b, cntb - c2);
ans = max(ans, ta + tb + c1 + c2);
}
if (p[i].f) c2++;
else c1++;
}
cout << ans << endl;
}
int main() {
int T;
cin >> T;
while (T--) {
solve();
}
return 0;
}
这是一个交互式问题
又是照着翻译看的
题意:后台有一个字符串长度为n,只由ab组成,你可通过最多n+2次询问,尝试得出字符串。每次你可以输出一个字符串,如果字符串完全匹配,则结束程序,否则给出不同的价值,这个价值表示其中一个字符串需要删除,变换多少次。
做法:首先用定义两个最长的全a和全b字符串,然后询问两次,这样可以判断字符串长度n,然后就可以挨着一位一位的判断了,最坏情况下刚刚n+2次。
//#include
//#include
//#include
//#include
//#include
//#include
#include "bits/stdc++.h"
using namespace std;
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
//#define ls(x) tr[x].ls
//#define rs(x) tr[x].rs
//#define lowbit(x) x&-x
const int inf = 0x3f3f3f3f;
const int maxn = 200000 + 10;
typedef long long ll;
int query(string s) {
cout << s << endl;
int ans;
cin >> ans;
if (ans <= 0) exit(0);
return ans;
}
int main() {
string s1, s2;
for (int i = 0; i < 300; i++)
s1 += 'a', s2 += 'b';
int na = 300 - query(s1);
int nb = 300 - query(s2);
int n = na + nb;
string ans;
for (int i = 0; i < n; i++) ans += 'a';
if (nb == 0) {
query(ans);
}
int tmp = nb;
for (int i = 0; i < n; i++) {
ans[i] = 'b';
int xx = query(ans);
if (xx > tmp) {
ans[i] = 'a';
} else {
tmp = xx;
}
}
return 0;
}
还是照着翻译看的
题意:给出一个n个点凸多边形,顶点用1-n随便编号,现在把他切成n-2个三角形,任意乱序给出n-2个三角形,尝试求出 顶点顺时针或者逆时针的编号并且任意起点都可以,以及三角形的切出顺序,任意一个即可。
做法:其实这题我是不怎么会的,题解也没有看懂。但不过看了一位大佬的代码,忽然好像就知道了。首先我们先考虑顶点编号,我们发现一条边最多会使用两次,对于只使用了一次的边肯定就是凸包的边了。我们考虑使用 x o r xor xor运算来解决这个问题,对于给出的三角形首先进行 对边用map进行标记记录下共用的三角形的标号,同时对顶点进行异或,如果是共用边,一个顶点异或两次没有影响,然后在map中找到任意一条只使用了一次的边的两个顶点,然后就可以用 x o r xor xor进行类似链表的操作得到答案。关于三角形的顺序这个我倒是想到了,共用边的两个三角形,建立一个无向图,然后dfs,从叶子向上输出就可以了。
//#include
//#include
//#include
//#include
//#include
//#include
#include "bits/stdc++.h"
using namespace std;
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
//#define ls(x) tr[x].ls
//#define rs(x) tr[x].rs
//#define lowbit(x) x&-x
const int inf = 0x3f3f3f3f;
const int maxn = 200000 + 10;
typedef long long ll;
map<pair<int, int>, vector<int> > mp;
vector<int> p[maxn];
int n, a, b, c, v[maxn], vis[maxn];
vector<int> pp;
void dfs(int u, int f) {
for (auto v:p[u]) {
if (v == f) continue;
dfs(v, u);
}
cout << u << ' ';
}
void solve() {
mp.clear();
cin >> n;
for (int i = 0; i <= n + 1; i++) {
v[i] = 0;
p[i].clear();
}
for (int i = 1; i <= n - 2; i++) {
cin >> a >> b >> c;
if (a > b) swap(a, b);
if (b > c) swap(b, c);
if (a > b) swap(a, b);
v[a] ^= b, v[a] ^= c;
v[b] ^= a, v[b] ^= c;
v[c] ^= b, v[c] ^= a;
mp[{a, b}].push_back(i);
mp[{b, c}].push_back(i);
mp[{a, c}].push_back(i);
}
for (auto H:mp) {
if (H.second.size() == 1) {
a = H.first.first;
b = H.first.second;
break;
}
}
cout << a << ' ' << b << ' ';
for (int i = 0; i < n - 2; i++, swap(a, b)) cout << (a ^= v[b]) << ' ';
cout << endl;
for (auto H:mp) {
if (H.second.size() == 2) {
p[H.second[0]].push_back(H.second[1]);
p[H.second[1]].push_back(H.second[0]);
}
}
dfs(1, 0);
// cout << pp.size() << endl;
// for (auto x:pp) {
// cout << x << " ";
// }
cout << endl;
}
int main() {
int T;
cin >> T;
while (T--) {
solve();
}
return 0;
}