<前言>
虽然全程睡觉,但是考得不错。
今早昨晚多晚睡我也就不说了,总之很困。就写了T1正解。
考试过程
T1
第一反应干草炸弹。
然后一个二分,判定的时候人傻了。直接计算不就好了写啥二分。
复杂度一算,单走一个树状数组,傻*。
然后睡了一场比赛。
T2
一开始题目出锅没看
后来不想看了
题解上一个二维最短路,s*。
T3
预处理+(dp),当时我tm直接睡着。
睡着前写了一个(dfs),实测5分;
T4
一看路径相关,反手一个点分。
然后发现有同色重复路径。
懒得管了,直接交,然后一分都没有。
考完之后我去接校车,结果等了半天发现不是今天(???)
然后就吃饭回寝
爽啦
Solution
[20200512普转提]T1 vr
大意
(N)个病毒,每个位置(x_i),生命值(h_i),每次攻击范围([x-d,x+d])范围内病毒,伤害为(W),则最少几次杀死所有病毒。
Solution
因为要消灭所有病毒,最左边的病毒一定要被消灭,不妨直接以最左边病毒位置为左端点释放攻击。
这是个显而易见的贪心,然后直到消灭所有病毒即可。
(Code:)
#include<bits/stdc++.h>
#define N 200010
#define int long long
using namespace std;
int n, d, k;
struct node
{
int x, h;
} a[N] = {};
int c[N] = {};
void inc(int x, int v)
{
for(; x <= N - 10; x += x & (-x))
c[x] += v;
}
int ask(int x)
{
int sum = 0;
for(; x; x -= x & (-x))
sum += c[x];
return sum;
}
inline int read()
{
int s = 0, w = 1;
char c = getchar();
while((c < '0' || c > '9') && c != '-')
c = getchar();
if(c == '-')w = -1, c = getchar();
while(c <= '9' && c >= '0')
s = (s << 3) + (s << 1) + c - '0', c = getchar();
return s * w;
}
inline bool cmp(node x, node y)
{
return x.x < y.x;
}
signed main()
{
freopen("vr.in", "r", stdin);
freopen("vr.out", "w", stdout);
n = read();
d = read();
k = read();
for(int i = 1; i <= n; ++i)
a[i].x = read(), a[i].h = read();
sort(a + 1, a + n + 1, cmp);
int tag = 1;
long long sum = 0;
for(int i = 1; i <= n; ++i)
{
int add = ask(i);
if(a[i].h + add * k <= 0)continue;
long long dec = (a[i].h + add * k + k - 1) / k;
while(a[tag].x <= a[i].x + 2 * d && tag <= n)
++tag;
inc(i, -dec);
inc(tag, dec);
sum += dec;
}
printf("%lld
", sum);
return 0;
}
[20200512普转提]T2 旅行花费
大意
有(n)个城市,它们由(m)条双向道路连接,保证它们能够彼此到达。
第(i)条道路连接(u_i,v_i),需要花费(x_i)个银币,耗费(t_i)秒的时间。每个城市处都有兑换银币处,第(i)个城市中你可以每次用(1)个金币兑换(c_i)个银币,可以兑换无限次,不过兑换(1)次需要花费(d_i)秒的时间。
你一开始在(1)号城市,有(s)个银币和无限多的金币,求到其它城市需要耗费的最小时间。
Solution
我们发现(x_ileq 50)且(Mleq 100),所以银币最多不过5000,再多也没用。
直接设置limit,然后把(位置,所剩银币)作为一个点去做二维最短路。
注意有很多细节比如如何获得答案?银币数的维护?
#include<bits/stdc++.h>
#define N 5010
#define fi first
#define se second
#define ll long long
#define mmp(x,y) make_pair(x,y)
using namespace std;
int n, m, s;
int c[N] = {}, d[N] = {};
inline int read()
{
int s = 0, w = 1;
char c = getchar();
while((c < '0' || c > '9') && c != '-')
c = getchar();
if(c == '-')w = -1, c = getchar();
while(c <= '9' && c >= '0')
s = (s << 3) + (s << 1) + c - '0', c = getchar();
return s * w;
}
ll dis[55][N] = {};
int vis[55][N] = {};
struct Graph
{
int net[N << 1], w[N << 1];
int to[N << 1], ti[N << 1];
int fl[N], len;
inline void inc(int x, int y, int z, int t)
{
to[++len] = y;
w[len] = z;
ti[len] = t;
net[len] = fl[x];
fl[x] = len;
}
} G;
priority_queue<pair<ll, pair<int, int> > >q;
void DJ(void)
{
memset(vis, 0, sizeof(vis));
memset(dis, 0x3f, sizeof(dis));
dis[1][min(s, 5000)] = 0;
q.push(mmp(-dis[1][min(s, 5000)], mmp(1, min(s, 5000))));
while(!q.empty())
{
int t = q.top().se.fi;
int s = q.top().se.se;
q.pop();
if(vis[t][s])continue;
vis[t][s] = 1;
if((dis[t][s] + d[t] < dis[t][min(s + c[t], 5000)]))
{
dis[t][min(s + c[t], 5000)] = (dis[t][s] + d[t]) * 1LL;
q.push(mmp(-dis[t][min(5000, s + c[t])], mmp(t, min(5000, s + c[t]))));
}
for(int i = G.fl[t]; i; i = G.net[i])
{
int v = G.to[i], z = G.w[i], ti = G.ti[i];
if(s < z)continue;
if(dis[t][s] + ti < dis[v][s - z])
{
dis[v][s - z] = 1LL * (dis[t][s] + ti);
q.push(mmp(-dis[v][s - z], mmp(v, s - z)));
}
}
}
}
signed main()
{
freopen("travel.in", "r", stdin);
freopen("travel.out", "w", stdout);
n = read();
m = read();
s = read();
for(int i = 1; i <= m; ++i)
{
int x = read(), y = read();
int z = read(), t = read();
G.inc(x, y, z, t);
G.inc(y, x, z, t);
}
for(int i = 1; i <= n; ++i)
{
c[i] = read();
d[i] = read();
}
DJ();
for(int i = 2; i <= n; ++i)
{
ll ans = 0x3f3f3f3f3f3f3f3f;
for(int j = 0; j <= 5000; ++j)
ans = min(ans, dis[i][j]);
printf("%lld
", ans);
}
return 0;
}
<后记>
后面的题目就鸽了吧。。
C题瞎搞有5分,D题我反手一个点分,明知道需要考虑重复色但是mode办法。
正解什么的根本没听(懂)。