JOISC 2020 补题记录

Day 1 和 Day 4 鸽了,Day 2 和 Day 3 打得像 ** 一样。

Day 2 T3 简单数数题拿到手就化了一堆奇怪的充要条件结果就只能 \O(n^4) dp 了,优化了很久(以为我的充要条件很靠谱),留了 20min rush 没写完,遗憾离场。Day 3 T2 4K- 的 DS 题调了一个小时还没调出来,遗憾离场。赛后 30min 才 AC

感觉这个 2020 年状态一直不太行……经常浮躁而无法静下来去分析一个问题试图突破……希望,能改改吧。感觉在理论状态下应该只有 D1T2 和 D4T2 两个题切不掉的……但实际去考有没有 175 + 200 + 205 + 200 都是个问题……

//先贴代码,题解想起来再补 代码也鸽了

D1T1

#include <bits/stdc++.h>
#define rep(i, n) for(int i = 0; i < (int)(n); i ++)
#define rep1(i, n) for(int i = 1; i <= (int)(n); i ++)
#define MP make_pair

using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int MOD = 998244353;

int n, a[1000005][2];
PII dp[1000005][2];

PII unite(const PII& u, const PII& v)
{
	if(u.first > u.second) return v;
	if(v.first > v.second) return u;
	return MP(min(u.first, v.first), max(u.second, v.second));
}

char ans[1000005];

int main()
{
	scanf("%d", &n);
	rep(i, 2) rep(j, 2 * n) scanf("%d", &a[j][i]);
	dp[0][0] = MP(0, 0);
	dp[0][1] = MP(1, 1);
	rep1(i, 2 * n - 1) {
		dp[i][0] = dp[i][1] = MP(0, -1);
		rep(j, 2) rep(k, 2) if(a[i - 1][k] <= a[i][j]) dp[i][j] = unite(dp[i][j], dp[i - 1][k]);
		dp[i][1].first ++;
		dp[i][1].second ++;
	}
	int ct = -1, cs = n;
	if(dp[2 * n - 1][0].first <= n && dp[2 * n - 1][0].second >= n) ct = 0;
	else if(dp[2 * n - 1][1].first <= n && dp[2 * n - 1][1].second >= n) ct = 1;
	if(ct == -1) {
		printf("-1\n");
		return 0;
	}
	for(int i = 2 * n - 1; i >= 0; i --) {
		cs -= ct;
		ans[i] = 'A' + ct;
		if(i == 0) break;
		int nt = -1;
		if(a[i - 1][0] <= a[i][ct] && dp[i - 1][0].first <= cs && dp[i - 1][0].second >= cs) nt = 0;
		else if(a[i - 1][1] <= a[i][ct] && dp[i - 1][1].first <= cs && dp[i - 1][1].second >= cs) nt = 1;
		ct = nt;
	}
	
	printf("%s\n", ans);
	return 0;
}

D1T2

这里面的 2-SAT 是假的,然而能通过所有数据(有一说一比这个更假的做法也能过(笑

#include <bits/stdc++.h>
#define rep(i, n) for(int i = 0; i < (int)(n); i ++)
#define rep1(i, n) for(int i = 1; i <= (int)(n); i ++)
#define MP make_pair

using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int INF = 0x3f3f3f3f;

int n, k;
int del[200005];
int xl[200005], yl[200005], xr[200005], yr[200005];
int permx[200005], permy[200005];
int xa[200005], ya[200005];

int sta[200005];
void occupy(int cx, int cy, int ck)
{
	rep(i, n) {
		if(del[i]) continue;
		if(xl[i] <= cx && yl[i] <= cy && xr[i] >= cx && yr[i] >= cy) del[i] = ck;
	}
}
void disocc(int ck)
{
	rep(i, n) if(del[i] == ck) del[i] = 0;
}

bool s_trivial(int ck, int retx[], int rety[])
{
	int xlm = -INF, xrm = INF, ylm = -INF, yrm = INF;
	rep(i, n) {
		if(del[i]) continue;
		xlm = max(xlm, xl[i]);
		xrm = min(xrm, xr[i]);
		ylm = max(ylm, yl[i]);
		yrm = min(yrm, yr[i]);
	}
	if(xlm == -INF) return true;
	if(ck == 0) return false;
	if(xlm <= xrm) {
		int cnt = 0, cr = INF;
		for(int i = n - 1; i >= 0; i --) {
			int cur = permy[i];
			if(del[cur]) continue;
			if(cr > yr[cur]) {
				cr = yl[cur];
				retx[cnt] = xlm;
				rety[cnt] = cr;
				cnt ++;
			}
		}
		return cnt <= ck;
	} else if(ylm <= yrm) {
		int cnt = 0, cr = INF;
		for(int i = n - 1; i >= 0; i --) {
			int cur = permx[i];
			if(del[cur]) continue;
			if(cr > xr[cur]) {
				cr = xl[cur];
				retx[cnt] = cr;
				rety[cnt] = ylm;
				cnt ++;
			}
		}
		return cnt <= ck;
	} else if(ck == 1) return false;
	
	occupy(xlm, ylm, ck);
	retx[0] = xlm;
	rety[0] = ylm;
	if(s_trivial(ck - 1, retx + 1, rety + 1)) return true;
	disocc(ck);
	
	occupy(xlm, yrm, ck);
	retx[0] = xlm;
	rety[0] = yrm;
	if(s_trivial(ck - 1, retx + 1, rety + 1)) return true;
	disocc(ck);
	
	occupy(xrm, ylm, ck);
	retx[0] = xrm;
	rety[0] = ylm;
	if(s_trivial(ck - 1, retx + 1, rety + 1)) return true;
	disocc(ck);
	
	occupy(xrm, yrm, ck);
	retx[0] = xrm;
	rety[0] = yrm;
	if(s_trivial(ck - 1, retx + 1, rety + 1)) return true;
	disocc(ck);
	return false;
}

int xs[400005], ys[400005], xtot, ytot, ltot;
int rgl[4][200005], rgr[4][200005];
int ver[4][200005], vcnt;
vector<int> G[4000015];
bool vis[4000015]; 
int ret[2000015];

void add_edge(int x, int y, int vx, int vy)
{
	G[x << 1 | vx ^ 1].push_back(y << 1 | vy);
	G[y << 1 | vy ^ 1].push_back(x << 1 | vx);
}

void dfs(int v)
{
	vis[v] = true;
	rep(i, G[v].size()) if(!vis[G[v][i]]) dfs(G[v][i]);
	if(ret[v >> 1] == -1) ret[v >> 1] = !(v & 1);
}

void s_ntrivial()
{
	int xlm = -INF, xrm = INF, ylm = -INF, yrm = INF;
	rep(i, n) {
		xlm = max(xlm, xl[i]);
		xrm = min(xrm, xr[i]);
		ylm = max(ylm, yl[i]);
		yrm = min(yrm, yr[i]);
	}
	
	rep(i, n) {
		xs[2 * i] = xl[i];
		xs[2 * i + 1] = xr[i];
	}
	sort(xs, xs + 2 * n);
	xtot = unique(xs, xs + 2 * n) - xs;
	rep(i, n) {
		ys[2 * i] = yl[i];
		ys[2 * i + 1] = yr[i];
	}
	sort(ys, ys + 2 * n);
	ytot = unique(ys, ys + 2 * n) - ys;
	
	rep(i, 4) rep(j, n) rgl[i][j] = rgr[i][j] = -1;
	rep(i, n) {
		int lx = xl[i] <= xrm;
		int rx = xr[i] >= xlm;
		int ly = yl[i] <= yrm;
		int ry = yr[i] >= ylm; 
		if(lx + rx + ly + ry >= 3) continue;
		if(lx) {
			rgl[0][i] = lower_bound(ys, ys + ytot, max(yl[i], yrm)) - ys;
			rgr[0][i] = lower_bound(ys, ys + ytot, min(yr[i], ylm)) - ys;
		}
		if(rx) {
			rgl[1][i] = lower_bound(ys, ys + ytot, max(yl[i], yrm)) - ys;
			rgr[1][i] = lower_bound(ys, ys + ytot, min(yr[i], ylm)) - ys;
		}
		if(ly) {
			rgl[2][i] = lower_bound(xs, xs + xtot, max(xl[i], xrm)) - xs;
			rgr[2][i] = lower_bound(xs, xs + xtot, min(xr[i], xlm)) - xs;
		}
		if(ry) {
			rgl[3][i] = lower_bound(xs, xs + xtot, max(xl[i], xrm)) - xs;
			rgr[3][i] = lower_bound(xs, xs + xtot, min(xr[i], xlm)) - xs;
		}
	}
	
	ltot = max(xtot, ytot) + 1;
	vcnt = 4 * ltot;
	rep1(i, ytot) add_edge(i - 1, i, 1, 0);
	rep1(i, ytot) add_edge(ltot + i - 1, ltot + i, 1, 0);
	rep1(i, xtot) add_edge(ltot * 2 + i - 1, ltot * 2 + i, 1, 0);
	rep1(i, xtot) add_edge(ltot * 3 + i - 1, ltot * 3 + i, 1, 0);
	
	rep(i, n) {
		int p0, p1;
		for(p0 = 0; p0 < 4 && rgl[p0][i] == -1; p0 ++) ;
		for(p1 = 3; p1 >= 0 && rgl[p1][i] == -1; p1 --) ;
		if(p1 == -1) continue;
		
		ver[p0][i] = vcnt ++;
		if(p1 > p0) ver[p1][i] = vcnt ++;
		add_edge(ver[p0][i], p0 * ltot + rgl[p0][i], 1, 1);
		add_edge(ver[p0][i], p0 * ltot + rgr[p0][i] + 1, 1, 0);
		if(p0 != -1) {
			add_edge(ver[p1][i], p1 * ltot + rgl[p1][i], 1, 1);
			add_edge(ver[p1][i], p1 * ltot + rgr[p1][i] + 1, 1, 0);
		}
		add_edge(ver[p0][i], ver[p1][i], 0, 0);
	}
	
	rep(i, vcnt) ret[i] = -1;
	rep(i, vcnt * 2) if(!vis[i]) dfs(i);
	
	rep(i, ytot + 1) if(ret[i] || i == ytot) {
		xa[0] = xrm;
		ya[0] = ys[max(i - 1, 0)];
		break;
	}
	rep(i, ytot + 1) if(ret[i + ltot] || i == ytot) {
		xa[1] = xlm;
		ya[1] = ys[max(i - 1, 0)];
		break;
	}
	rep(i, xtot + 1) if(ret[i + ltot * 2] || i == xtot) {
		ya[2] = yrm;
		xa[2] = xs[max(i - 1, 0)];
		break;
	}
	rep(i, xtot + 1) if(ret[i + ltot * 3] || i == xtot) {
		ya[3] = ylm;
		xa[3] = xs[max(i - 1, 0)];
		break;
	}
}

template<int* arr>
bool cmp(int i, int j)
{
	return arr[i] < arr[j];
}

int main()
{
	scanf("%d%d", &n, &k);
	rep(i, n) scanf("%d%d%d%d", &xl[i], &yl[i], &xr[i], &yr[i]);
	
	r
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值