A. Diagonal Walking

题意

将一个序列中所有的\('RU'\)或者\('UR'\)替换成\('D'\),问最终得到的序列最短长度为多少。

思路

贪心

Code

#include <bits/stdc++.h>
#define F(i, a, b) for (int i = (a); i < (b); ++i)
#define F2(i, a, b) for (int i = (a); i <= (b); ++i)
#define dF(i, a, b) for (int i = (a); i > (b); --i)
#define dF2(i, a, b) for (int i = (a); i >= (b); --i)
#define maxn 110
using namespace std;
char s[maxn];
typedef long long LL;
int main() {
int n, cnt=0;
scanf("%d%s", &n, s);
bool used=0;
F(i, 1, n) {
if (!used && ((s[i]=='U'&&s[i-1]=='R') || (s[i]=='R'&&s[i-1]=='U'))) {
++cnt, used = true;
}
else used = false;
}
printf("%d\n", n-cnt);
return 0;
}

B. String Typing

题意

要得到一个字符串,有两种操作:

  1. 打印一个字符
  2. 将前面打印过的部分拷贝一遍跟在后面;

    第二种方法最多只能使用一次

问要打印一个字符串最少的操作次数。

思路

数据量暴力可过,但是还是拿来回忆了下后缀数组。

题目即是要求最长的\(A\),使得原字符串\(S\)可表示为\(AAB\)的形式。

通过后缀数组的\(height\)数组,可以知道原串与每一个后缀的\(LCP\)长度,要能够拷贝,满足的条件是:

  1. 该后缀与原串的\(LCP\)长度\(\geq\)两者之间的起始位置差
  2. 该后缀与原串间的起始位置差\(*2\leq\)原串的长度

在所有满足条件的当中取个最大值即可。

Code

#include <bits/stdc++.h>
#define F(i, a, b) for (int i = (a); i < (b); ++i)
#define F2(i, a, b) for (int i = (a); i <= (b); ++i)
#define dF(i, a, b) for (int i = (a); i > (b); --i)
#define dF2(i, a, b) for (int i = (a); i >= (b); --i)
#define maxn 1010
using namespace std;
int wa[maxn], wb[maxn], wv[maxn], wt[maxn], h[maxn], rk[maxn], sa[maxn], n, m, tot, r[maxn];
char s[maxn];
bool cmp(int* r, int a, int b, int l) { return r[a] == r[b] && r[a+l] == r[b+l]; }
void init(int* r, int* sa, int n, int m) {
int* x=wa, *y=wb, *t, i, j, p;
for (i = 0; i < m; ++i) wt[i] = 0;
for (i = 0; i < n; ++i) ++wt[x[i] = r[i]];
for (i = 1; i < m; ++i) wt[i] += wt[i - 1];
for (i = n-1; i >= 0; --i) sa[--wt[x[i]]] = i; for (j = 1, p = 1; p < n; j <<= 1, m = p) {
for (p = 0, i = n-j; i < n; ++i) y[p++] = i;
for (i = 0; i < n; ++i) if (sa[i] >= j) y[p++] = sa[i] - j; for (i = 0; i < n; ++i) wv[i] = x[y[i]]; for (i = 0; i < m; ++i) wt[i] = 0;
for (i = 0; i < n; ++i) ++wt[wv[i]];
for (i = 1; i < m; ++i) wt[i] += wt[i - 1];
for (i = n-1; i >= 0; --i) sa[--wt[wv[i]]] = y[i]; t = x, x = y, y = t, x[sa[0]] = 0;
for (p = 1, i = 1; i < n; ++i) x[sa[i]] = cmp(y, sa[i], sa[i-1], j) ? p - 1 : p++;
} for (i = 0; i < n; ++i) rk[sa[i]] = i;
int k = 0;
for (i = 0; i < n - 1; h[rk[i++]] = k) {
for (k = k ? --k : 0, j = sa[rk[i] - 1]; r[i+k] == r[j+k]; ++k);
}
}
int main() {
scanf("%d%s", &n, s);
F(i, 0, n) m = max(r[tot++]=s[i], m); r[tot++] = 0;
init(r, sa, tot, ++m);
int p = rk[0], maxx = 0;
dF2(i, p-1, 1) {
if (h[i+1]>=sa[i] && (sa[i]<<1)<=n) maxx = max(maxx, sa[i]);
h[i] = min(h[i], h[i+1]);
}
F(i, p+1, tot) {
if (h[i]>=sa[i] && (sa[i]<<1)<=n) maxx = max(maxx, sa[i]);
h[i+1] = min(h[i], h[i+1]);
}
printf("%d\n", maxx?n-maxx+1:n);
return 0;
}

C. Matrix Walk

题意

一个\(N\times M\)的方格纸,从左到右从上到下分别标号\(1,2,\ldots,N\times M\). 在每一个格子中只能向上下左右相邻的四个格子走。

现给出一个行走序列,要求给出一组合法的\(N,M\). 或者指出不存在。

思路

注意到,合法的序列差只可能为\(1\)或者定值\(M\).

在满足该条件的基础上,还要注意不能从最右边的格子\(+1\),不能从最左边的格子\(-1\).

注意一些细节即可。

Code

#include <bits/stdc++.h>
#define F(i, a, b) for (int i = (a); i < (b); ++i)
#define F2(i, a, b) for (int i = (a); i <= (b); ++i)
#define dF(i, a, b) for (int i = (a); i > (b); --i)
#define dF2(i, a, b) for (int i = (a); i >= (b); --i)
#define maxn 200010
using namespace std;
typedef long long LL;
int a[maxn];
int main() {
int n, y;
scanf("%d", &n);
F(i, 0, n) scanf("%d", &a[i]);
F(i, 1, n) {
y = abs(a[i]-a[i-1]);
if (y==0) { puts("NO"); return 0; }
if (y>1) break;
}
if (y==1) { puts("YES"); printf("%d %d\n", 1, 1000000000); }
else {
F(i, 1, n) {
if (a[i]-a[i-1]==1) {
if (a[i-1]%y==0) { puts("NO"); return 0; }
}
else if (a[i]-a[i-1]==-1) {
if (a[i]%y==0) { puts("NO"); return 0; }
}
else if (abs(a[i]-a[i-1])!=y) { puts("NO"); return 0; }
}
puts("YES");
printf("%d %d\n", 1000000000, y);
}
return 0;
}

D. Fight Against Traffic

题意

给定一张图和起点\(s\)终点\(t\),现在原图不相邻的两点之间加一条边,问有多少种加边方式会不导致\(s\)到\(t\)之间的距离缩短。

思路

若加边导致距离缩短,则必经过刚加的边,假设加的边为\((u,v)\),原\(s,t\)的距离为\(d\),图中所有顶点到\(s\)的最短路距离为\(dist1[]\),到\(t\)的最短路距离为\(dist2[]\)则必有$$dist1[u]+1+dist2[v]\lt d$$或者

\[dist1[v]+1+dist2[u]\lt d
\]

枚举边根据上述条件\(check\)即可。

Code

#include <bits/stdc++.h>
#define F(i, a, b) for (int i = (a); i < (b); ++i)
#define F2(i, a, b) for (int i = (a); i <= (b); ++i)
#define dF(i, a, b) for (int i = (a); i > (b); --i)
#define dF2(i, a, b) for (int i = (a); i >= (b); --i)
#define maxn 1010
struct Edge { int to, ne; }edge[maxn<<1];
int tot, ne[maxn], dist1[maxn], dist2[maxn];
bool vis[maxn], mp[maxn][maxn];
void add(int u, int v) {
edge[tot] = {v, ne[u]};
ne[u] = tot++;
}
struct node {
int v, c;
bool operator < (const node& nd) const { return c > nd.c; }
};
using namespace std;
typedef long long LL;
void dij(int src, int* dist) {
memset(vis, 0, sizeof vis);
memset(dist, 0x3f, maxn*sizeof(int));
vis[src] = true; dist[src] = 0;
priority_queue<node> q;
while (true) {
for (int i = ne[src]; ~i; i = edge[i].ne) {
int v = edge[i].to;
if (vis[v]) continue;
if (dist[src]+1<dist[v]) {
dist[v] = dist[src]+1;
q.push({v, dist[v]});
}
}
while (!q.empty() && vis[q.top().v]) q.pop();
if (q.empty()) break;
vis[src=q.top().v] = true;
}
}
int main() {
memset(ne, -1, sizeof ne);
int n, m, s, t, u, v;
scanf("%d%d%d%d", &n, &m, &s, &t);
F(i, 0, m) {
scanf("%d%d", &u, &v);
add(u, v), add(v, u);
mp[u][v] = mp[v][u] = true;
}
dij(s, dist1);
dij(t, dist2);
int cur = dist1[t], ans = 0;
F2(i, 1, n) {
F2(j, i+1, n) {
if (mp[i][j]) continue;
if (dist1[i]+1+dist2[j]>=cur && dist2[i]+1+dist1[j]>=cur) ++ans;
}
}
printf("%d\n", ans);
return 0;
}

E. Water Taps

题意

\(n\)个水龙头,流量分别为\(a_1,a_2,\ldots,a_n\),温度分别为\(t_1,t_2,\ldots,t_n\),打开若干个水龙头放水,假设放出的水量分别为\(x_1,x_2,\ldots,x_n\),则得到的水温为

\[\frac{\sum_{i=1}^{n}x_it_i}{\sum_{i=1}^{n}x_i}
\]

现要得到温度为\(T\)的水,求能放出的水量的最大值。

思路

因为

\[\frac{\sum_{i=1}^{n}x_it_i}{\sum_{i=1}^{n}x_i}=T
\]

所以

\[\sum_{i=1}^{n}x_i(t_i-T)=0
\]

因此将所有的\(t_i\)减去\(T\)之后,每个水龙头对温度的贡献就分为正贡献和负贡献。

正的放在一边,负的放在一边,因为能取小数,所以少的一边必能取满。

而要多的那边能取到尽量多的\(x\),只要\(t\)尽量小,所以将\(t\)从小到大排序后取即可。

Code

#include <bits/stdc++.h>
#define F(i, a, b) for (int i = (a); i < (b); ++i)
#define F2(i, a, b) for (int i = (a); i <= (b); ++i)
#define dF(i, a, b) for (int i = (a); i > (b); --i)
#define dF2(i, a, b) for (int i = (a); i >= (b); --i)
#define maxn 200010
using namespace std;
typedef long long LL;
struct node {
LL x, t;
bool operator < (const node& nd) const { return t < nd.t; }
}a[maxn];
int main() {
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
int n, T;
scanf("%d%d", &n, &T);
F(i, 0, n) scanf("%I64d", &a[i].x);
F(i, 0, n) scanf("%I64d", &a[i].t), a[i].t-=T;
sort(a, a+n);
int p2=0, p1=-1;
double ans=0;
for (; p2<n; ++p2) {
if (a[p2].t<0) p1=p2;
else if (!a[p2].t) ans += a[p2].x;
if (a[p2].t > 0) break;
}
if (p1==-1||p2==n) printf("%.8f\n", ans);
else {
LL sum1=0, sum2=0;
dF2(i, p1, 0) sum1-=a[i].x*a[i].t;
F(i, p2, n) sum2+=a[i].x*a[i].t;
if (sum1>=sum2) {
F(i, p2, n) ans += a[i].x;
int i=p1;
for (; i >= 0; --i) {
if (sum2-a[i].x*(-a[i].t)<0) break;
ans += a[i].x;
sum2 += a[i].x*a[i].t;
}
if (i>=0&&sum2) ans += 1.0*sum2/(-a[i].t);
}
else {
dF2(i, p1, 0) ans += a[i].x;
int i=p2;
for (; i < n; ++i) {
if (sum1-a[i].x*a[i].t<0) break;
ans += a[i].x;
sum1 -= a[i].x*a[i].t;
}
if (i<n&&sum1) ans += 1.0*sum1/a[i].t;
}
printf("%.8f\n", ans);
}
return 0;
}

G. Castle Defense

题意

数轴上\(n\)个位置每个位置放有若干个弓箭手,弓箭手的攻击范围为左右大小为\(r\)的范围内。

一个点的防御程度定义为 该点能被多少个弓箭手攻击到。整条放线的防御程度定义为其上所有点防御程度的 最小值

现可以在防线上增添\(k\)个弓箭手,要求使防线的防御程度最大化,求这个最大值

思路

最小值的最大值,首先显然二分答案。

对于初始固定的弓箭手,一段一段的线段覆盖,可以用前缀和差分来处理。

之后二分答案时的\(check\)怎么进行呢?

用一个变量记录至今为止多放置了多少个弓箭手,从左到右扫

  1. 若位置\(i\)不够,则要在位置\(i+r+1\)补弓箭手
  2. 考虑到位置\(i\)时,要记得消除掉前面的\(i-r-1\)位置的影响

复杂度\(O(n\log n)\)

Code

#include <bits/stdc++.h>
#define F(i, a, b) for (int i = (a); i < (b); ++i)
#define F2(i, a, b) for (int i = (a); i <= (b); ++i)
#define dF(i, a, b) for (int i = (a); i > (b); --i)
#define dF2(i, a, b) for (int i = (a); i >= (b); --i)
#define maxn 500010
using namespace std;
typedef long long LL;
int n, d; LL k;
LL sum[maxn], a[maxn], add[maxn];
bool check(LL x) {
memset(add, 0, sizeof add);
LL temp=0, tot=0;
F2(i, 1, n) {
temp -= (i>=d+2 ? add[i-d-1] : 0);
if (x<=sum[i]+temp) continue;
int p = min(i+d, n);
add[p] = x - (sum[i] + temp);
tot += add[p];
if (tot>k) return false;
temp = x-sum[i];
}
return true;
}
int main() {
scanf("%d%d%I64d", &n, &d, &k);
F2(i, 1, n) {
scanf("%I64d", &a[i]);
int l=max(i-d, 1), r=min(n+1, i+d+1);
sum[l]+=a[i], sum[r]-=a[i];
}
F2(i, 1, n) sum[i] += sum[i-1];
LL l=0, r=2e18, ans;
while (l<=r) {
LL mid=l+r>>1;
if (check(mid)) ans=mid, l=mid+1;
else r=mid-1;
}
printf("%I64d\n", ans);
return 0;
}

Educational Codeforces Round 40 A B C D E G的更多相关文章

  1. Educational Codeforces Round 40 (Rated for Div. 2) 954G G. Castle Defense

    题 OvO http://codeforces.com/contest/954/problem/G 解 二分答案, 对于每个二分的答案值 ANS,判断这个答案是否可行. 记 s 数组为题目中描述的 a ...

  2. Educational Codeforces Round 40 F. Runner's Problem

    Educational Codeforces Round 40 F. Runner's Problem 题意: 给一个$ 3 * m \(的矩阵,问从\)(2,1)$ 出发 走到 \((2,m)\) ...

  3. Educational Codeforces Round 40千名记

    人生第二场codeforces.然而遇上了Education场这种东西 Educational Codeforces Round 40 下午先在家里睡了波觉,起来离开场还有10分钟. 但是突然想起来还 ...

  4. Educational Codeforces Round 40 C. Matrix Walk( 思维)

    Educational Codeforces Round 40 (Rated for Div. 2) C. Matrix Walk time limit per test 1 second memor ...

  5. Educational Codeforces Round 40 (Rated for Div. 2) Solution

    从这里开始 小结 题目列表 Problem A Diagonal Walking Problem B String Typing Problem C Matrix Walk Problem D Fig ...

  6. Educational Codeforces Round 40 I. Yet Another String Matching Problem

    http://codeforces.com/contest/954/problem/I 给你两个串s,p,求上一个串的长度为|p|的所有子串和p的差距是多少,两个串的差距就是每次把一个字符变成另一个字 ...

  7. Educational Codeforces Round 40 G. Castle Defense (二分+滑动数组+greedy)

    G. Castle Defense time limit per test 1.5 seconds memory limit per test 256 megabytes input standard ...

  8. Educational Codeforces Round 40 (Rated for Div. 2)

    A. Diagonal Walking time limit per test 1 second memory limit per test 256 megabytes input standard ...

  9. Educational Codeforces Round 58 A,B,C,D,E,G

    A. Minimum Integer 链接:http://codeforces.com/contest/1101/problem/A 代码: #include<bits/stdc++.h> ...

随机推荐

  1. Qt Qwdget 汽车仪表知识点拆解2 图像放大

    先贴上效果图,注意,没有写逻辑,都是乱动的 这里讲下 这个小汽车的进入过程,其实这个说白了就没有技术含量了,本来应该趁着这个机会学习一下Qt的动画机制,不过随机一想,这个自己写也累不到那里去 下面说下 ...

  2. python中socket、socketio、flask-socketio、WebSocket的区别与联系

    socket.socketio.flask-socketio.WebSocket的区别与联系 socket 是通信的基础,并不是一个协议,Socket是应用层与TCP/IP协议族通信的中间软件抽象层, ...

  3. Laxcus大数据管理系统2.0(4)- 第一章 基础概述 1.3 节点

    1.3 节点 按照我们给Laxcus集群的设计定义,Laxcus集群被分为内部和外部两个网络环境.内部网络由集群的所有权人负责实施和管理,为保证集群能够有效可靠运行,需要遵守一系列的集群部署和管理规定 ...

  4. ubuntu apache2配置,包括虚拟机配置

    虚拟机设置好了之后,需要在/etc/hosts里面添加  127.0.0.1  www.baidu.com   跟在windows里hosts里配置是一样的

  5. 【iOS开发】iOS对UIViewController生命周期和属性方法的解析

    iOS对UIViewController生命周期和属性方法的解析 一.引言 作为MVC设计模式中的C,Controller一直扮演着项目开发中最重要的角色,它是视图和数据的桥梁,通过它的管理,将数据有 ...

  6. 【积累】根据CheckBox的不选中 ,用JQuery 清除 RidaoButtonList 的选中项

    如题,项目要求无刷新更新数据. 1)Web页面布局 Html以及效果图  

  7. 微信公众号开发java框架:wx4j(MaterialUtils篇)

    wx4j-MaterialUtils的使用 函数说明:上传永久视频素材 参数:文件路径.视频描述(通过setter填充内容即可) 返回值:微信服务器返回的json字符串 public static S ...

  8. 【历史】- UNIX发展史(BSD,GNU,linux)

    先前的一個理想 UNIX 系统自 1969 年 Ken Thompson 与 Dennis Ritchie 在美国贝尔电话实验室(Bell Telephone Laboratories)发展出雏形至今 ...

  9. Delphi 检查文件是否存在

    Delphi下检查文件是否存在,我们可以使用FileExists函数 其原形如下: Function FileExists(const FileName: string): Boolean; 示例: ...

  10. oracle序列使用时 先用伪列将序列的id调整到正确的位置