补题
DIV3(1324A-E)
一
1324A - Yet Another Tetris Problem
挂了一次是因为没有break
1324B - Yet Another Palindrome Problem
找出长度为3的回文串即可
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define INF 0x3f3f3f3f;
const int maxn = 5 * 1e3 + 5;
using namespace std;
int t, n,a[maxn];
struct P {
int c1, c2;
}book[maxn][maxn];
void ini() {
for (int i = 1;i <= n;i++)
for (int j = 1;j <= n;j++)
book[i][j].c1 = book[i][j].c2 = 0;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(false);
cin >> t;
while (t--) {
ini();
bool f = 0;
cin >> n;
for (int i = 1;i <= n;i++) {
cin >> a[i];
}
for (int i = 1;i <= n;i++) {
for (int j = 1;j <= n;j++) {
if (j < i) {
book[i][a[j]].c1++;
}
else if (j > i) {
book[i][a[j]].c2++;
}
if (book[i][a[j]].c1 && book[i][a[j]].c2) {
f = 1;
puts("YES");
break;
}
}
if (f) break;
}
if (!f) puts("NO");
}
return 0;
}
1324C - Frog Jumps
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define INF 0x3f3f3f3f;
const int maxn = 1e9 + 5;
using namespace std;
int t , l;
string s;
bool check(int x) {
int last = -1;
for(int i = l - 1;i >= 0;i--) {
if (s[i] == 'R') {
if (last != -1 && last - i > x)
{
return false;
}
last = i;
}
}
if (last != -1 && last + 1 <= x) return 1;
return 0;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(false);
cin >> t;
while(t--) {
cin >> s;
l = s.length();
int L = 1, R = l+1;
for (int i = l - 1;i >= 0;i--) {
if (s[i] == 'R') {
L = l - i;
break;
}
}
//cout << "R: " << R << endl;
while (L < R) {
int mid = (L + R) >> 1;
if (check(mid)) {
R = mid;
//cout << mid << " OK" << endl;
}
else {
L = mid+1;
//cout << mid << " tNOT OK" << endl;
}
}
cout << L << endl;
}
return 0;
}
1324D - Pair of Topics
(1)二分
一个二分想了好久 果然又是long long 的问题orz
觉得有必要整理一下二分模板了
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define INF 0x3f3f3f3f;
const int maxn = 2 * 1e5 + 5;
using namespace std;
int n,a[maxn],b[maxn];
long long ans;
bool check(int x,int y) {
return a[x] + a[y] >0 ;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(false);
cin >> n;
for (int i = 1;i <= n;i++) cin >> a[i];
for (int i = 1;i <= n;i++) { cin >> b[i]; a[i] -= b[i]; }
sort(a + 1, a + 1 + n);
for (int i = 1;i <= n;i++) {
long long L = i + 1, R = n;
while (L < R) {
long long mid = (L + R) >> 1;
if (check(i,mid)) {
//cout << mid << " OK" << endl;
R = mid;
}
else {
//cout << mid << " NOT OK" << endl;
L = mid+1;
}
}
//cout << "+" << n - L+1 << endl;
if(check(i,L)) ans += (n - L+1);
}
cout << ans << endl;
return 0;
}
另一种做法用到了
(2)树状数组
用来求和
也复习一下树状数组吧
1324E - Sleeping Schedule
dp了
预处理注意
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define INF 0x3f3f3f3f;
const int maxn = 2 * 1e3 + 5;
using namespace std;
int n, h, l, r;
int t[maxn],dp[maxn][maxn];
int main() {
ios::sync_with_stdio(false);
cin.tie(false);
cin >> n >> h >> l >> r;
for (int i = 0;i <= n;i++) {
for (int j = 0;j <= h;j++) {
dp[i][j] = -0x3f3f3f3f;
}
}
dp[0][0] = 0;
for (int i = 1;i <= n;i++) cin >> t[i];
for (int i = 1;i <= n;i++) {
for (int j = 0;j < h;j++) {
dp[i][j] = max(dp[i-1][(j-t[i]+h)%h], dp[i-1][(j-t[i]+1+h)%h]);
dp[i][j] += (j >= l && j <= r);
}
}
int ans = 0;
for (int i = 0;i < h;i++) {
ans = max(ans, dp[n][i]);
}
cout << ans << endl;
return 0;
}
二 Div3(1328)
A - Divisibility Problem
签到
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 2e9
using namespace std;
const int maxn = 1e5 + 5;
int a,b,t;
int main() {
cin >> t;
while (t--) {
cin >> a >> b;
if (a%b == 0) cout << 0 << endl;
else {
cout << b - a % b << endl;
}
}
return 0;
}
B - K-th Beautiful String
构造1+2+…+n
longlong引发的惨案+1,一气之下全开了longlong
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 2e9
using namespace std;
const int maxn = 1e5 + 5;
long long n,t;
long long k;
int main() {
cin >> t;
while (t--) {
cin >> n >> k;
long long l = 0,d=0;
string ans;
for (long long i = 1;i <= maxn;i++) {
long long test = i*(i-1)/2;
if (test>= k) {
l = i;
d = test - k;
break;
}
}
for (int i = 1;i <= n - l;i++) {
ans += 'a';
}
ans += 'b';
for (int i = 1;i <= d;i++) {
ans += 'a';
}
ans += 'b';
for (int i = 1;i <= l - d - 2;i++) {
ans += 'a';
}
cout <<ans<< endl;
}
return 0;
}
C - Ternary XOR
方法是贪心,思想是构造
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 2e9
using namespace std;
const int maxn = 1e5 + 5;
int t, n;
string x;
int main() {
cin >> t;
while (t--) {
string a, b;
bool ok = 0;
cin >> n >> x;
for (int i = 0;i < x.length();i++) {
if (x[i] == '0') {
a += '0';b += '0';
}
if (x[i] == '1') {
if (!ok) {
a += '1';b += '0';
ok = 1;
}
else {
a += '0';b += '1';
}
}
if (x[i] == '2') {
if (!ok) {
a += '1';b += '1';
}
else {
a += '0';b += '2';
}
}
}
cout << a << endl << b << endl;
}
return 0;
}
D - Carousel
有必要说一下题意(一直以为题意错了
共有n个位置,给出很多动物种类,排成一个环,每个位置放一个动物,染色,要求相邻的不同种类动物不能拥有相同的颜色,求最小颜色数量。
一开始莫名其妙联想到了四色定理,然后GG
一波模拟挂了,不知何解。
思路大致如下:如果相同动物连在一起,涂相同的颜色;如果相邻颜色不同,间隔开涂;唯一可能造成答案为3的情况是因为是环,涂到第n个的时候发现与第一个冲突了,而又不能改成与n-1相同的颜色,所以要加一得到3.
过了。。要分奇偶讨论,并且所有数字一样的时候特判答案是1
当有循环结构的时候,下标1-n没有0-n-1愉悦
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 2e9
using namespace std;
const int maxn = 3e5 + 5;
int q, n,a[maxn],ans[maxn];
int main() {
cin >> q;
while (q--) {
cin >> n;
int tot = 1;
for (int i = 1;i <= n;i++) cin >> a[i];
bool f = 1;
for (int i = 1;i <= n;i++) {
if (a[i] != a[1]) {
f = 0;
break;
}
}
if (f) {
for (int i = 1;i <= n;i++)
ans[i] = 1;
}
else {
if (n % 2 == 0) {
tot++;
for (int i = 1;i <= n;i++) {
ans[i] = i % 2 ==0 ? 1 : 2;
}
}
else {
bool okk = 0;
//虽然n是奇数,但凡有1个重复的,都可以转化为偶数解决问题
for (int i = 1;i <= n;i++) {
if (i == n && a[i] == a[1] && !okk) {
okk = 1;ans[i] = ans[1];
}
if (a[i] == a[i - 1] && !okk) {
okk = 1; ans[i] = ans[i - 1];
}
else {
ans[i] = ans[i - 1] == 1 ? 2 : 1;
}
}
if (okk) tot = 2;
else tot = 3, ans[n] = 3;
}
}
cout << tot << endl;
for (int i = 1;i <=n;i++)
cout << ans[i] << " ";
cout <<endl;
}
return 0;
}
三 周末练习
cf好像裂开了 自闭中
题意
B 一个读题的 签到
//B
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define pi pcos(-1.0)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
string s;
int main() {
cin.tie(false);
ios::sync_with_stdio(false);
cin >> s;
int cc = 0,ss = 0;
for (int i = 0;i < s.length();i++) {
if (s[i] == 'C') {
cc++;
if (cc == 3) {
cc = 0;
cout << "P";
}
else
cout << "B";
ss = 0;
}
else {
ss++;
if (ss == 3) {
ss = 0;
cout << "T";
}
else cout << "D";
cc = 0;
}
}
return 0;
}
C DFS
终于敲出来了,和数独差不多 开几个数组记录
以下来自dalao代码
//i
#include"pch.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define pi pcos(-1.0)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int maxn = 3e5 + 5;
bool vis[10][10], col[10][10], row[10][10], reg[40][10],b[10][10];
int mp[10][10], n,v[40],cur[40],a[10][10];
int process(string x) {
int res = 0;
for (int i = 0;i < x.length();i++) {
res *= 10;
res += x[i] - '0';
}
return res;
}
bool ok() {
for (int i = 1;i <= n;i++)cur[i] = 0;
for (int i = 1;i <= 6;i++) {
for (int j = 1;j <= 6;j++) {
cur[mp[i][j]] += a[i][j];
}
}
for (int i = 1;i <= n;i++) {
if (cur[i] != v[i]) return 0;
}
return 1;
}
void print() {
for (int i = 1;i <= 6;i++) {
for (int j = 1;j <= 6;j++) {
cout << a[i][j] << " ";
}
cout << endl;
}
}
int id(int x, int y) {
return (x - 1) / 2 * 2 + (y - 1) / 3 + 1;
}
bool can(int x, int y, int i) {
if (!(row[x][i]) && !col[y][i] && !b[id(x, y)][i] && !reg[mp[x][y]][i]) {
if (cur[mp[x][y]] + i <= v[mp[x][y]])return 1;
}
return 0;
}
void deal(int x, int y, int i, int f) {
a[x][y] = i;
row[x][i] = col[y][i] = b[id(x, y)][i] = reg[mp[x][y]][i] = f;
if (f) {
cur[mp[x][y]] += i;
}
else {
cur[mp[x][y]] -= i;
}
return;
}
bool dfs(int x, int y) {
if (x == 7) {
if (ok()) return 1;
return 0;
}
bool f = 0;
for (int i = 1;i <= 6;i++) {
if (can(x, y, i)) {
deal(x, y, i, 1);
if (y < 6) f = dfs(x, y + 1);
else f = dfs(x + 1, 1);
if (f)return 1;
deal(x, y, i, 0);
}
}
return 0;
}
int main() {
cin >> n;for (int i = 1;i <= n;i++)cin >> v[i];
for (int i = 1;i <= 6;i++){
for (int j = 1;j <= 6;j++) {
string x;cin >> x;
mp[i][j] = process(x);
}
}
dfs(1, 1);
print();
return 0;
}
这是我的代码,比较(非常 )丑
注释掉的部分是cur数组的正确用法,至于我这样的,完全就是浪费时间啊…不知会不会tle,不过正确用法比上面那个快一点点耶(转圈圈
解除标记的时候要记得减去cur,如果不用记录,那就要清空a数组,这就是debug一下午的原因((
//c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define pi pcos(-1.0)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int maxn = 3e5 + 5;
bool vis[10][10], col[10][10], row[10][10], reg[40][10],b[10][10];
int mp[10][10], n,v[40],cur[40],a[10][10];
int process(string x) {
int res = 0;
for (int i = 0;i < x.length();i++) {
res *= 10;
res += x[i] - '0';
}
return res;
}
bool ok() {
for (int i = 1;i <= n;i++)cur[i] = 0;
for (int i = 1;i <= 6;i++) {
for (int j = 1;j <= 6;j++) {
cur[mp[i][j]] += a[i][j];
}
}
for (int i = 1;i <= n;i++) {
if (cur[i] != v[i]) return 0;
}
return 1;
}
void print() {
for (int i = 1;i <= 6;i++) {
for (int j = 1;j <= 6;j++) {
cout << a[i][j] << " ";
}
cout << endl;
}
cout << endl;
}
bool notok() {
for (int i = 1;i <= n;i++)cur[i] = 0;
for (int i = 1;i <= 6;i++) {
for (int j = 1;j <= 6;j++) {
cur[mp[i][j]] += a[i][j];
}
}
for (int i = 1;i <= n;i++) {
if (cur[i] > v[i]) {
return 1;
}
}
return 0;
}
bool flag = 0;
void findans(int r,int c) {
if (flag)return;
if (r == 7) {
if (ok()) { print(); flag = 1; }
return;
}
for (int i = 1;i <= 6;i++) {
if (!row[r][i] && !col[c][i]
&& !b[(r - 1) / 2 * 2 + (c - 1) / 3 + 1][i]
&& !reg[mp[r][c]][i]
&& !notok()) {
row[r][i] = col[c][i] = 1;
b[(r - 1) / 2 * 2 + (c - 1) / 3 + 1][i] = 1;
reg[mp[r][c]][i] = 1;
a[r][c] = i;
//cur[mp[r][c]] += i;
if (flag) return;
else if (c == 6) findans(r + 1, 1);
else findans(r, c + 1);
row[r][i] = col[c][i] = 0;
b[(r - 1) / 2 * 2 + (c - 1) / 3 + 1][i] = 0;
reg[mp[r][c]][i] = 0;
a[r][c] = 0;
//cur[mp[r][c]] -= i;
}
}
return;
}
int id(int x, int y) {
return (x - 1) / 2 * 2 + (y - 1) / 3 + 1;
}
int main() {
cin >> n;for (int i = 1;i <= n;i++)cin >> v[i];
for (int i = 1;i <= 6;i++){
for (int j = 1;j <= 6;j++) {
string x;cin >> x;
mp[i][j] = process(x);
}
}
findans(1,1);
return 0;
}
D. Doll Collector 签到
求出最大的满足n*(n+1)/2 < x的n即可(x为输入值)
E
FFT, 菜鸡还没有真正学会过。。
F. Frieza Frenzy
队友写的 据说是并查集 然而我GG了
顺道回去复习了并查集,准备补带权值的并查集了((真就递归学习啊
噢 原来是一个倒着的并查集,利用了起始连通的条件。
倒着看,假设起始时所有点离散,当一个点被拆除(即进行连接操作)时,与他相连的所有边(如果他们本来不相连)变为一个联通块,更新联通块的个数,直到最后所有点都连通。
因为这里是倒着来的,所以答案也倒着输出,用减法统计。
//i
#include"pch.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define pi pcos(-1.0)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mp make_pair
using namespace std;
const int maxn = 1e5 + 5;
int n, m,d[maxn],ans[maxn],f[maxn];
struct E {
int u, v;
}edge[maxn];
int find(int x) {
return f[x] == x ? x : find(f[x]);
}
void merge(int x, int y) {
f[x] = y;
return;
}
int main() {
cin >> n >> m;
for (int i = 1;i <= m;i++) {
cin >> edge[i].u >> edge[i].v;
}
for (int i = 1;i <= m;i++) cin >> d[i];
for (int i = 1;i <= n;i++)f[i] = i;
int cnt = n;
for (int i = m;i >= 1;i--) {
int x = find(edge[d[i]].u);
int y = find(edge[d[i]].v);
if (x != y) {
cnt--;
merge(x, y);
}
ans[i-1] = cnt;
}
ans[m] = n;
for (int i = 1;i <= m;i++) {
cout << ans[i] << endl;
}
return 0;
}
G 看起来像是数学题
H. Heaven’s Arena
cout << n+0.01*(ap+(-a)(100-p))<
I. Important Equipment
计算几何 我要鞭挞我自己 最后还是要靠好队友
一直在看,从没有写出来过
两种方法
(1)求交点个数-神奇的结论(适用于任何多边形)
经过一点任意作一条射线(为了方便我们一般做与xy轴垂直的线哈),求解出与多边形每条边所在直线的交点总个数,
若为奇数,则此点在多边形外部;
若为偶数,则此点在多边形内部。
代码明天明天吧qwq 噫在睡前写完了,不过已经是明天了
比较多细节,要判断与边重合、在边上,不考虑水平线
,考虑垂直线,如果不是垂线那么x交点要在右侧才可加入有效计数。
交点法还没debug出来 假代码
请注意 是错的嗷
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int maxn = 1e3 + 5;
const double eps = 1e-5;
int s, r, m,n;
struct P {
int x, y;
};
struct A {
P stk[maxn];
int top;
}a[5];
bool onesegment(P pi, P pj, P Q) {
//判断是否共线 叉积等于0且在线段上
if ((Q.x - pi.x)*(pj.y - pi.y) == (pj.x - pi.x)*(Q.y - pi.y)
&& min(pi.x, pj.x) <= Q.x && max(pi.x, pj.x) >= Q.x
&& min(pi.y, pj.y) <= Q.y && max(pi.y, pj.y) >= Q.y)
return true;
return false;
}
bool insidepolpgon(P t,int id) {
int cnt = 0;
double xinters;
P p1 = a[id].stk[0],p2;
for (int i = 0;i < a[id].top;i++) {
p2 = a[id].stk[i % (a[id].top)];
if (onesegment(p1, p2, t))
return true;
//水平边不做考虑,首先要在范围内
if (t.y > min(p1.y, p2.y) &&
t.y <= max(p1.y, p2.y)&&
t.x <= max(p1.x, p2.x)&&
p1.y != p2.y)
{
xinters = (t.y - p1.y)*(p2.x - p1.x) / (p2.y - p1.y) + p1.x;
if (p1.x == p2.x || t.x <= xinters)
cnt++;
}
p1 = p2;
}
if (cnt % 2 == 0) return false;
return true;
}
string ans(int id) {
if (id == 0)return "Sheena";
if (id == 1)return "Rose";
if (id == 2)return "Maria";
return "";
}
void process(int n, int id) {
for (int i = 1;i <= n;i++) {
int xx, yy; cin >> xx >> yy;
int num = a[id].top;
a[id].stk[num].x = xx;a[id].stk[num].y = yy;
a[id].top++;
}
}
int main() {
cin.tie(false);
ios::sync_with_stdio(false);
cin >> s >> r >> m;
process(s, 0);process(r, 1);process(m, 2);
P t;cin >> n;
for (int i = 1;i <= n;i++) {
cin >> t.x >> t.y;
bool flag = 0;
for (int id = 0;id < 3 && !flag;id++) {
if (insidepolpgon(t, id)) {
flag = true;
cout << ans(id) << endl;
}
}
if (!flag) cout << "Outside" << endl;
}
return 0;
}
(2)叉积 -(只适用于凸多边形的算法)
自己又加了一个判断条件,cf炸了还没来得及交,明天交交看。
至少在无限debug的痛苦中我再一次复习了无数遍叉积
(x1y2-x2y1)设三点分别为P1,P2,P0,
那么以P0为向量的出发点,叉积为
X(p1-p0)*Y(p2-p0)-X(p2-p0)*Y(p1-p0)
超大声bb
以及学会了判断点在直线左边、右边还是直线上的方法:也是叉积
左边>0,右边<0,直线上=0(以P0为向量出发点)
以及找出了练习时一直GG的原因,因为判断的时候点落在了某块多边形区域的延长线上,虽然不在但是判断是=0的并没有异号所以就漏掉了。
真是悲伤的故事啊
(更新于第二天(x)
debug了一上午 发现是longlong的问题
自 我 枪 毙
//i
#include"pch.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define pi pcos(-1.0)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef long long ll;
using namespace std;
const int maxn = 1e3 + 5;
int s, r, m, n;
struct P {
int x, y;
};
struct A {
P stk[maxn]; int top;
int minx, maxx, miny, maxy;
}a[3];
void process(int n, int id) {
a[id].maxx = a[id].maxy = 0;
a[id].minx = a[id].miny = maxn;
for (int i = 1;i <= n;i++) {
int xx, yy; cin >> xx >> yy;
int num = a[id].top;
a[id].stk[num].x = xx;a[id].stk[num].y = yy;
a[id].top++;
a[id].maxx = max(a[id].maxx, xx);a[id].maxy = max(a[id].maxy, yy);
a[id].minx = min(a[id].minx, xx);a[id].miny = min(a[id].miny, yy);
}
}
//没错就是这里 嘤嘤嘤
ll multi(P p1, P p2, P p0) {
ll ans = (ll)((ll)((p1.x - p0.x)*(ll)(p2.y - p0.y))) - (ll)((ll)(p2.x - p0.x)*(ll)(p1.y - p0.y));
return ans;
}
//这个可以省略 不知到会不会快些
bool out(P p, A a) {
if (p.x<a.minx || p.x>a.maxx || p.y<a.miny || p.y>a.maxy)
return true;
return false;
}
bool isinside(P p, A a) {
//此句可省
if (out(p, a)) return false;
//
for (int i = 0;i < a.top;i++)
if (multi(a.stk[i], a.stk[(i + 1) % a.top], p) < 0)
return false;
return true;
}
string ans(int id) {
if (id == 0)return "Sheena";
if (id == 1)return "Rose";
if (id == 2)return "Maria";
return "";
}
int main() {
cin.tie(false);ios::sync_with_stdio(false);
cin >> s >> r >> m; process(s, 0);process(r, 1);process(m, 2);
cin >> n;
while(n--){
P t; cin >> t.x >> t.y; bool flag = 0;
for (int id = 0;id < 3 && !flag;id++) {
if (isinside(t, a[id])) {
flag = true; cout << ans(id) << endl;
}
}
if (!flag) cout << "Outside" << endl;
}
return 0;
}
ok了,好累
J - Jaeger Training
寻找s[i]前值大于等于s[i]的个数,队友写的,据说归并排序模板可
更新于两天后-------补完了,确实是归并排序改一改,更新答案记得标记序号
归并时候的逆序数(不是严格意义上的逆序数,因为相等也算)与这个数所处的位置有关,
ans[num]+=他前面的个数
写完一瞄,几乎和队友一模一样。。可能是模板的原因吧orz
//i
#include"pch.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define pi pcos(-1.0)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int maxn = 5e5 + 5;
int n,ans[maxn];
struct P {
int v, id;
}s[maxn], tmp[maxn];
void mergearray(P a[], int L,int mid, int R, P t[]) {
int i = L, j = mid + 1, mm = mid, nn = R,k=0;
while (i <= mm && j <= nn) {
if (a[i].v < a[j].v) t[k++] = a[i++];
else {
t[k++] = a[j]; ans[a[j++].id] += mm - i + 1;
//cout << ans[j] << endl;
}
}
while (i <= mm) t[k++] = a[i++];
while (j <= nn) t[k++] = a[j++];
for (int i = 0;i < k;i++) a[L + i] = t[i];
}
void mergesort(P a[], int L, int R, P t[]) {
if (L < R) {
int mid = (L + R) >> 1;
mergesort(a, L, mid, t);
mergesort(a, mid + 1, R, t);
mergearray(a, L, mid, R, t);
}
return;
}
int main() {
cin.tie(false);ios::sync_with_stdio(false);
cin >> n;for (int i = 0;i < n;i++) {cin >> s[i].v; s[i].id = i;}
mergesort(s, 0, n - 1, tmp);
//for (int i = 0;i < n;i++)cout << s[i].v << endl;
for (int i = 0;i < n;i++) { cout << n-ans[i] << " "; }
return 0;
}
K. Killua’s Race 图论
这个还没懂…
L 记忆化dp
建图有点复杂…TLE
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define pi pcos(-1.0)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int maxn = 1e5 + 5, inf = 0x3f3f3f3f;
int n, l,dp[maxn];
struct P {
int x, y;
bool operator<(P &a) {
if (x != a.x) return x < a.x;
return y < a.y;
}
}p[maxn];
struct node {
int y, index;
node(int a, int b) {
y = a;index = b;
}
bool operator<(node & a) {
if (a.y != y) return y < a.y;
return index < a.index;
}
};
map<int, pair<int, int>> f;
set<int> s;
vector<node> id[maxn];
vector<int> X[maxn], edge[maxn];
int DFS(int u) {
if (dp[u]) return dp[u];
int res = 0;
for (auto v:edge[u]) {
res = max(res, DFS(v));
}
if (edge[u].size() == 0) {
//可以到达
if (u == n + 1) return dp[u] = 1;
else return dp[u] = -maxn;
}
if (res == 0) return dp[u] = -maxn;
else return dp[u] = res + 1;
}
int main() {
cin.tie(0);ios::sync_with_stdio(false);
cin >> n >> l;
p[0].x = p[0].y = 0;
p[n + 1].x = l;p[n + 1].y = 0;
X[0].push_back(0);
id[0].push_back(node(0, 0));
X[l].push_back(0);
id[l].push_back(node(0, n + 1));
f[0] = make_pair(0, 0);
f[n + 1] = make_pair(l, 0);
s.insert(0);s.insert(l);
for(int i = 1;i <= n;i++) {
cin >> p[i].x >> p[i].y;
id[p[i].x].push_back(node(p[i].y,i));
X[p[i].x].push_back(p[i].y);
s.insert(p[i].x);
f[i] = make_pair(p[i].x, p[i].y);
}
sort(p, p + n + 2);
for (auto i = s.begin();i != s.end();i++) {
int k = *i;
sort(X[k].begin(), X[k].end());
sort(id[k].begin(), id[k].end());
}
//这是优化,只在可能的范围内找出符合条件的点,建边
//约束条件(x+=5,abs相加小于5),使用X存储(x,y),id存储y对应的序号,如果不是重复点就建边
for (int i = 0;i <= n;i++) {
int x = f[i].first;
int y = f[i].second;
for (int xx = x + 1;xx <= x + 5;xx++) {
int d = 5 - (xx - x);
int pos1 = lower_bound(X[xx].begin(), X[xx].end(), y - d) - X[xx].begin();
int pos2 = upper_bound(X[xx].begin(), X[xx].end(), y + d) - X[xx].begin();
//没找到
if (pos1 == X[xx].size()) continue;
//全都符合
if (pos2 == X[xx].size()) pos2 = X[xx].size() - 1;
for (int k = pos1; k <= pos2;k++) {
int idd = id[xx][k].index;
int yy = id[xx][k].y;
if (abs(yy - y) + abs(xx - x) > 5) continue;
//if (i != idd) {
//建边
edge[i].push_back(idd);
//}
}
}
}
//减2是因为开头结尾
cout << DFS(0) - 2 << endl;
return 0;
}
ECNA 2016 又开新坑
B - Foosball Dynasty
模拟(其实我挺喜欢做模拟(小声bb 这大概就是菜狗吧
从下午debug到晚上
使用map记录每个人加入的时间,然后注意一下题目要求
以及:get swap对于string可能会造成迭代器失效
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 2e9
using namespace std;
const int maxn = 1e5 + 5;
int n,last;
map<string, int> mp;
struct P {
int id;
string df, of;
}w, b;
struct Team {
string fis,sec;
};
Team team[maxn];int tot = 0;
string info;
queue<string> q;
int cur=0,rec;
void okk(P &win,P &lose) {
//cur记录的是最长连胜数
if (last == win.id)
cur++;
else {
last = 1-last;
cur = 1;
}
Team m;
if (cur >= rec) {
if (mp[win.df] > mp[win.of]) {
m.fis = win.df; m.sec = win.of;
}
else {
m.fis = win.of;m.sec = win.df;
}
tot = (cur == rec ? tot: 0);
team[++tot] = m;
rec = cur;
}
/*
string tmp = win.df;
win.df = win.of;
win.of = tmp;
*/
//SWAP函数对string函数容易造成迭代器失效
swap(win.df, win.of);
string now = q.front();q.pop();
q.push(lose.df);
lose.df = lose.of;
lose.of = now;
mp[lose.df] = 2;
mp[lose.of] = 1;
}
void print() {
for (int i = 1;i <= tot;i++)
cout << team[i].fis << " " << team[i].sec << endl;
}
int main() {
cin >> n;
w.id = 0;b.id = 1;
cin >> w.of >> b.of >> w.df >> b.df;
mp[w.of] = mp[b.of] = 2;mp[w.df] =mp[b.df]=1;
for (int i = 5;i <= n;i++) {
string x;cin >> x;
q.push(x);
}
cin >> info;
if (info[0] == 'W') last = 0;
else last = 1;
for (int i = 0;i < info.length();i++) {
if (info[i] == 'W') okk(w, b);
else okk(b, w);
}
print();
return 0;
}
C-The Key to Cryptography
#include
#include
#include
#include
#include
#include
#define inf 2e9
using namespace std;
const int maxn = 3e5+5;
int main() {
string s, t,ans;
cin >> s >> t;
for (int i = 0;i < s.length();i++) {
char x = char((s[i] - t[i] + 26)%26 +'A');
ans += x;
t += x;
}
cout << ans << endl;
return 0;
}
D Lost in Translation
BFS也可以用MST
真的自闭了
#include
#include
#include
#include
#include
#include
#include
#define inf 2e9
using namespace std;
const int maxn = 3e3 + 5;
map<string, int> mp;
int n, m, res;
struct P {
int nxt, to, w;
}edge[maxn];
int E[maxn][maxn];
vector<int> Dep[maxn];
int dis[maxn], ans[maxn];
void bfs() {
queue<int>Q;
memset(dis, -1, sizeof(dis));
int st = 1;Q.push(st);
dis[st] = 0;ans[st] = 0;
while (!Q.empty()) {
int u = Q.front();Q.pop();
for (int i = 1;i <= n + 1;i++) {
if (E[u][i] && (dis[i] == -1 || dis[i] >= dis[u] + 1)) {
if(dis[i]!=dis[u]+1)
dis[i] = dis[u] + 1;
ans[i] = min(ans[i], E[u][i]);
Q.push(i);
}
}
}
return;
}
int main() {
memset(head, -1, sizeof(head));
scanf_s("%d%d", &n, &m);
for (int i = 1;i <= n;i++) {
string s; cin>>s;
mp[s] = i + 1;
ans[i + 1] = inf;
}
mp["English"] = 1;ans[1] = inf;
for (int i = 1;i <= m;i++) {
string u, v;int w;
cin >> u >> v >> w;
E[mp[u]][mp[v]] = w;
E[mp[v]][mp[u]] = w;
}
bfs();
for (int i = 1;i <= n + 1;i++) {
if (dis[i] == -1) {
puts("Impossible");
return 0;
}
else res+=ans[i];
}
printf("%d\n", res);
return 0;
}
另一种写法orz
#include"pch.h"
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 2e9
using namespace std;
const int maxn = 1e5 + 5;
struct E {
int nxt, to, w;
}edge[maxn << 1];
int head[maxn], tot = 0,vis[maxn];
void add(int u, int v, int w) {
edge[tot].to = v;
edge[tot].w = w;
edge[tot].nxt = head[u];
head[u] = tot++;
}
unordered_map<string, int> mmp;
int n, m,res;
#define f first
#define s second
#define mp make_pair
#define pii pair
void BFS() {
int cnt = 0;
queue<int> Q;
Q.push(0);vis[0] = 1;
priority_queue<pii, vector<pii>, greater<pii>> P;
while (cnt < n) {
while (!Q.empty()) {
int u = Q.front();Q.pop();
for (int i = head[u];~i;i = edge[i].nxt) {
if (!vis[edge[i].to])
P.push(mp(edge[i].w, edge[i].to));
}
}
int tmp = 0;
while (!P.empty()) {
auto x = P.top();P.pop();
if (!vis[x.s]) {
Q.push(x.s);
vis[x.s] = 1;
res += x.f;
cnt++;
tmp++;
}
}
if (!tmp) break;
}
if (cnt < n) {
puts("Impossible"); return;
}
else cout << res << endl;
}
string u, v;int w;
int main() {
memset(head, -1, sizeof(head));
cin >> n >> m;
for (int i = 1;i <= n;i++) {
cin >> u;
mmp[u] = i;
}
mmp["English"] = 0;
for (int i = 1;i <= m;i++) {
cin >> u >> v >> w;
add(mmp[u], mmp[v], w);add(mmp[v], mmp[u], w);
}
BFS();
return 0;
}
E.Red Rover
暴力即可
不知道为什么老爱用cin
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define pi pcos(-1.0)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int maxn = 1e5;
map<string,int> mp;
string s;
int check(string x) {
int res = 0;
for (int i = 0;i < s.length();) {
//cout << i << endl;
bool f = 1;
for (int j = 0;j < x.length() && f;j++) {
if (s[i + j] != x[j]) {
f = 0;
break;
}
}
if (f) {
res++;
i += x.length();
}
else i++;
}
return res;
}
int ans = 0x3f3f3f3f;
int main() {
cin >> s;
ans = s.length();
for (int i = 0;i < s.length();i++) {
for (int j = i;j < s.length();j++) {
string t = s.substr(i, j-i+1);
mp[t] = check(t);
ans = min(ans,int(s.length()-mp[t]*t.length()+mp[t]+t.length()));
}
}
cout << ans << endl;
return 0;
}
F-Removal Game
区间dp
代码来自dalao
#include"pch.h"
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 2e9
using namespace std;
const int maxn = 3e3 + 5;
int n,a[maxn],dp[maxn][maxn];
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a%b);
}
int main() {
while (cin >> n && n) {
for (int i = 1;i <= n;i++) cin >> a[i];
for (int i = 0;i <= n;i++)
for (int j = 0;j <= n;j++)
dp[i][j] = inf;
for (int len = 1;len <= n-1;len++) {
for (int i = 1;i <= n;i++) {
int j = i + len > n ? i+len-n:i+len;
if (len == 1) dp[i][j] = 0;
else {
for (int k = i + 1;k < j;k++) {
int nk = k > n ? k - n : k;
dp[i][j] = min(dp[i][j], dp[i][nk] + dp[nk][j] + gcd(a[i], a[j]));
}
}
}
}
int ans = inf;
for (int i = 1;i <= n - 1;i++) {
for (int j = i + 1;j <= n;j++) {
ans = min(ans, dp[i][j] + dp[j][i]+gcd(a[i], a[j]));
}
}
cout << ans << endl;
}
return 0;
}
G - That’s One Hanoi-ed Teacher
这个有点好玩哇,汉诺塔的递推,用dfs实现的,队友写的超级短
将三根柱子命名为1,2,3,则n阶汉诺塔完成的过程可以分为以下2种情况
1.n在1上,已知f(n)=2^(n-1),可以退化为n-1阶问题,(1,3,2,n-1)
2.n在3上,把n-1个叠到他上面去(2,1,3,n-1)
n在2上不合法
(其实就是把n=2时的简单情况拓展以下,把最上面想象成n-1个)
#include
#include
#include
#define inf 1e9
using namespace std;
const int maxn = 100005;
int f[maxn];bool GG = 0;
long long ans = 0;
//移动x个盘子 从a到c
void DFS(int a, int b, int c, int x) {
//cout << x << " from " << a << " to " << c << endl;
if (x == 0 || GG) return;
if (f[x] == a) {
//最大的盘子在出发点
ans += pow(2,x-1);
//移动其他x-1个盘子(从出发点到终点)
DFS(a, c, b, x - 1);
}
if (f[x] == b)
GG = 1;
if (f[x] == c)
//最大的盘子在终点
//移动其他的盘子从中转点到终点
DFS(b, a, c, x - 1);
}
int main() {
cin.tie(0);ios::sync_with_stdio(0);
int n = 0;
for (int i = 1;i <= 3;i++) {
int num;cin >> num;;
for (int j = 1;j <= num;j++) {
int x;cin >> x;
n = max(n, x);
f[x] = i;
}
}
DFS(1,2,3,n);
if (GG) cout << "No" << endl;
else cout << ans << endl;
return 0;
}
H BFS找出两个交叉点 标记区域(明天补
统计区域里的个数
(-------更新于第二天---------)
ok了,get了在框内选取一个点的方法,可以根据第一次出现的位置和区域的特性判断
舒 服 了
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 2e9
using namespace std;
const int maxn = 1e5 + 5;
int r, c,tot;
int nxt[4][2] = {{0,1},{0,-1},{-1,0},{1,0} };
char M[105][105],mA[105][105],mB[105][105];
struct P {
char id;
int x, y;
P():x(),y(){}
P(int a,int b):x(a),y(b){}
P(int a, int b, char c) :x(a), y(b), id(c) {}
}inter[3],A,B,sA,sB;
//标记是否越界
bool in(int x, int y) {
return (x >= 1 && x <= r && y >= 1 && y <= c);
}
//判断十字
bool iscross(int x, int y) {
return (in(x, y) && M[x][y] == 'X' &&M[x][y - 1] == 'X'&&M[x][y + 1] == 'X'&&M[x - 1][y] == 'X'&&M[x + 1][y] == 'X');
}
//是否碰到十字
bool touch(P p) {
for (int i = 1;i <= 2;i++)
if (p.x == inter[i].x && p.y == inter[i].y) return 1;
return 0;
}
//降维orz
int id(P p) {
return (p.x - 1)*c + p.y;
}
//BFS用的,分别标记A和B,最后分别统计,在初始的图上标记改动
bool vis[maxn],book[maxn];
void inivis() {
for (int i = 1;i <= 2;i++) vis[id(inter[i])] = 0;
}
void inibook() {
for (int i = 1;i <= r;i++)
for (int j = 1;j <= c;j++)
book[id(P(i, j))] = 0;
}
void getcnt(char m[105][105],P now,int t) {
inibook(); queue<P> QQ;
QQ.push(now);
book[id(now)] = 1; M[now.x][now.y]+=t;
while (!QQ.empty()) {
P cur = QQ.front();QQ.pop();
for (int k = 0;k < 4;k++) {
P np = P(cur.x + nxt[k][0], cur.y + nxt[k][1], cur.id);
if (in(np.x, np.y) && m[np.x][np.y] != now.id && !book[id(np)]) {
book[id(np)] = 1;
if (m[np.x][np.y] == '.') M[np.x][np.y]+=t;
QQ.push(np);
}
}
}
}
void BFS(char m[105][105],P cur) {
inivis(); queue<P> Q;
Q.push(cur); vis[id(cur)] = 1;
while (!Q.empty()) {
P now = Q.front();Q.pop();
for (int k = 0;k < 4;k++) {
P np = P(now.x + nxt[k][0], now.y + nxt[k][1], now.id);
if (in(np.x, np.y) && !vis[id(np)] && m[np.x][np.y]!='.'){
if (touch(np)) {
vis[id(np)] = 1;
m[np.x][np.y] = cur.id;
np = P(np.x + nxt[k][0], np.y + nxt[k][1], now.id);
}
vis[id(np)] = 1;
m[np.x][np.y] = cur.id;
Q.push(np);
}
}
}
}
//设第一个出现的A的坐标(i,j),则依据题意(i+1,j+1)一定落在该区域内
//所以用这个点作为bfs的起点 qwq
P findFirst(char m[105][105],char x) {
for (int i = 1;i <= r;i++) {
for (int j = 1;j <= c;j++) {
if (m[i][j] == x) {
return P(i+1, j+1, x);
}
}
}
return P(0, 0, '0');
}
void printAns() {
int ans1=0, ans2=0, ans3=0;
for (int i = 1;i <= r;i++) {
for (int j = 1;j <= c;j++) {
if (M[i][j] == '0')ans1++;
if (M[i][j] == '1')ans2++;
if (M[i][j] == '3')ans3++;
}
}
cout << ans1 << " " << ans2 << " " << ans3 << endl;
}
int main() {
cin >> r >> c;
for (int i = 1;i <= r;i++) {
for (int j = 1;j <= c;j++) {
cin >> M[i][j];
if (M[i][j] == 'A')A = P(i, j,'A');
if (M[i][j] == 'B')B = P(i, j,'B');
mA[i][j] =mB[i][j]=M[i][j];
}
}
for (int i = 1;i <= r;i++) {
for (int j = 1;j <= c;j++) {
if (iscross(i, j)) {
inter[++tot] = P(i, j,'X');
}
}
}
BFS(mA,A); sA = findFirst(mA, 'A');
BFS(mB,B); sB = findFirst(mB,'B');
getcnt(mA, sA, 2); getcnt(mB, sB, 3);
printAns();
return 0;
}
I - Waif Until Dark
Dinic网络流O(n* n *m)
当场挂机,落泪
建立源点汇点,连接人和源点,人和玩具,玩具和种类,种类和汇点。
注意这里的边权起到约束的作用(就是网络流定义哇),没有种类归属的玩具可以直接与汇点相连,个数限制无限个
WA了一次是因为 把人和源点之间的权值设置成了+oo,应该是1,因为只需要保证每个人一个玩具就可
#include
#include
#include
#include
#include
#define inf 2e9
using namespace std;
const int maxn = 3e5+5;
//网络最大流模板
//注意edge两倍大小哇
struct P {
int nxt, to, w;
}edge[maxn];
int tot=-1, n, m,p, head[maxn];
void add(int u, int v, int w) {
edge[++tot].nxt = head[u];
edge[tot].to = v;
edge[tot].w = w;
head[u] = tot;
}
int ans,S,T;
int dis[maxn],book[maxn];
queue<int> Q;
int bfs() {
memset(dis, -1, sizeof(dis));
while (!Q.empty()) Q.pop();
dis[S] = 0;
Q.push(S);
//BFS计算层数
while (!Q.empty()) {
int u = Q.front();
Q.pop();
for (int i = head[u];i != -1;i = edge[i].nxt) {
int v = edge[i].to;
if (dis[v] == -1 && edge[i].w) {
dis[v] = dis[u] + 1;
Q.push(v);
}
}
}
//能否到达汇点
return dis[T] != -1;
}
//把int写成bool,我怕不是个傻子吧..........
int dfs(int u, int exp) {
if (u == T) return exp;
int flow = 0, tmp = 0;
for (int i = head[u];i != -1;i = edge[i].nxt) {
int v = edge[i].to;
if (dis[v] == dis[u] + 1 && edge[i].w) {
tmp = dfs(v, min(exp, edge[i].w));
if (!tmp) continue;
exp -= tmp;
flow += tmp;
edge[i].w -= tmp;
//^1代表反向边
edge[i ^ 1].w += tmp;
}
if (!exp) dis[u] = 0;
}
return flow;
}
int main() {
memset(head, -1, sizeof(head));
scanf_s("%d%d%d", &n, &m, &p);
S = 0;T = n + m + p + 1;
for (int i = 1;i <= n;i++) {
//连接人和源点
add(S, i, 1);add(i, S, 0);
int t;scanf_s("%d", &t);
for (int j = 1;j <= t;j++) {
int id;scanf_s("%d", &id);
//人和玩具
add(i, n+id, 1);
add(n+id, i, 0);
}
}
for (int i = 1;i <= p;i++) {
int t;scanf_s("%d", &t);
for (int j = 1;j <= t;j++) {
int id;scanf_s("%d", &id);
book[id]=1;
//玩具和种类
add(n + id, n+m+i, 1);
add(n+m+i, n + id, 0);
}
int lim;scanf_s("%d", &lim);
//种类和汇点
add(m + n + i, T, lim);
add(T, m + n + i, 0);
}
for (int i = 1;i <= m;i++) {
if (!book[i]) {
//没有种类约束的玩具,直接连接到汇点
//只能选1个
add(n+i, T, 1);
add(T, n+i, 0);
}
}
while (bfs()) ans += dfs(S, inf);
printf("%d\n", ans);
return 0;
}
经过此题,收获了一个优雅(并不)的板子