联赛模拟测试18(A.施工未补)

B.蔬菜

非正解二维莫队碾过

vegetable
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define int long long
using namespace std;

inline int read(){
	int x = 0, w = 1;
	char ch = getchar();
	for(; ch > '9' || ch < '0'; ch = getchar()) if(ch == '-') w = -1;
	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
	return x * w;
}

inline void write(register int x){
	if(x < 0) x = ~x + 1, putchar('-');
	if(x > 9) write(x / 10);
	putchar(x % 10 + '0');
}

int s1, s2;
const int ss = 205;

struct node{
	int lx, ly, rx, ry, id;
	inline bool operator < (const node &a) const {
		register int lx1 = (lx - 1) / s1 + 1, lx2 = (a.lx - 1) / s1 + 1;
		register int rx1 = (rx - 1) / s1 + 1, rx2 = (a.rx - 1) / s1 + 1;
		register int ly1 = (ly - 1) / s2 + 1, ly2 = (a.ly - 1) / s2 + 1;
		return lx1 == lx2 ? rx1 == rx2 ? ly1 == ly2 ? (ly1 & 1) ? ry < a.ry : ry > a.ry : (rx1 & 1) ? ly1 < ly2 : ly1 > ly2 : (lx1 & 1) ? rx1 < rx2 : rx1 > rx2 : lx1 < lx2;
	}
}q[1000005];

int a[ss][ss], b[40005], cnt, s[40005], sum, ans[1000005];
inline int binary_search(register int x){
	register int l = 1, r = cnt;
	while(l < r){
		register int mid = l + r >> 1;
		if(b[mid] >= x) r = mid;
		else l = mid + 1;
	}
	return l;
}

inline void add1(register int u, register int l, register int r){
	for(register int i = l; i <= r; i++){
		sum += (s[a[u][i]] * 2 + 1);
		s[a[u][i]]++;
	}
}

inline void add2(register int u, register int l, register int r){
	for(register int i = l; i <= r; i++){
		sum += (s[a[i][u]] * 2 + 1);
		s[a[i][u]]++;
	}
}

inline void del1(register int u, register int l, register int r){
	for(register int i = l; i <= r; i++){
		sum += (1 - s[a[u][i]] * 2);
		s[a[u][i]]--;
	}
}

inline void del2(register int u, register int l, register int r){
	for(register int i = l; i <= r; i++){
		sum += (1 - s[a[i][u]] * 2);
		s[a[i][u]]--;
	}
}

signed main(){
	freopen("vegetable.in", "r", stdin);
	freopen("vegetable.out", "w", stdout);
	register int r = read(), c = read(), Q = read();
	s1 = sqrt(r), s2 = sqrt(c);
	for(register int i = 1; i <= r; i++)
		for(register int j = 1; j <= c; j++)
			a[i][j] = read(), b[++cnt] = a[i][j];
	
	sort(b + 1, b + 1 + cnt);
	cnt = unique(b + 1, b + 1 + cnt) - b - 1;
	for(register int i = 1; i <= r; i++)
		for(register int j = 1; j <= c; j++)
			a[i][j] = binary_search(a[i][j]);
	/*
	for(register int i = 1; i <= r; i++, puts(""))
		for(register int j = 1; j <= c; j++)
			cout << a[i][j] << " ";
	*/	
	for(register int i = 1; i <= Q; i++)
		q[i] = (node){read(), read(), read(), read(), i};
	sort(q + 1, q + 1 + Q);
	
	register int lx = 1, ly = 1, rx = 1, ry = 1;
	s[a[1][1]] = 1, sum = 1;
	for(register int i = 1; i <= Q; i++){
		while(lx > q[i].lx) add1(--lx, ly, ry);
		while(rx < q[i].rx) add1(++rx, ly, ry);
		while(ry < q[i].ry) add2(++ry, lx, rx);
		while(ly > q[i].ly) add2(--ly, lx, rx);
		while(lx < q[i].lx) del1(lx++, ly, ry);
		while(rx > q[i].rx) del1(rx--, ly, ry);
		while(ry > q[i].ry) del2(ry--, lx, rx);
		while(ly < q[i].ly) del2(ly++, lx, rx);
		ans[q[i].id] = sum;
	}
	for(register int i = 1; i <= Q; i++)
		cout << ans[i] << '
';
	return 0;
}

C.联盟

真的写吐了
改了四节课
昨天下午出了第一个部分分的时候激动的差点哭了出来

然后今天上午才把(60pts)完完整整码完
满分做法是(o(n))处理树及子树的直径
然而感觉实现有点困难
啊不
是的确困难
写不出来惹
回头再说

Leaque
/* cinput
4
1 2
2 3
3 4
*/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define min(a, b) (a) < (b) ? (a) : (b)
using namespace std;

inline int read(){
	int x = 0, w = 1;
	char ch = getchar();
	for(; ch > '9' || ch < '0'; ch = getchar()) if(ch == '-') w = -1;
	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
	return x * w;
}

inline void write(register int x){
	if(x < 0) x = ~x + 1, putchar('-');
	if(x > 9) write(x / 10);
	putchar(x % 10 + '0');
}

const int ss = 300010;

struct node{
	int from, to, nxt;
}edge[ss << 1];

int head[ss], tot = 1;
inline void add(register int u, register int v){
	edge[++tot].to = v;
	edge[tot].from = u;
	edge[tot].nxt = head[u];
	head[u] = tot;
}

bool vis[ss << 1];
int dis[ss], fa[ss], from, to, id, maxx, dep[ss];
inline void dfs(register int u, register int f){
	if(dis[u] > maxx) to = u, maxx = dis[u];
	dep[u] = dep[f] + 1;
	for(register int i = head[u]; i; i = edge[i].nxt){
		register int v = edge[i].to;
		if(v == f || vis[i]) continue;
		dis[v] = dis[u] + 1;
		fa[v] = u;
		dfs(v, u);
	}
}

inline void diameter(register int u){}

inline int jump(register int u, register int d){
	while(d--) u = fa[u];
	return u;
}

inline int getlen(register int id){
	register int u = edge[id].from;
	register int v = edge[id].to;
	vis[id] = vis[id ^ 1] = 1;

	memset(dis, 0, sizeof dis); to = 0;
	maxx = -1, dfs(u, u);
	memset(dis, 0, sizeof dis);
	maxx = -1, dfs(to, to);
	register int len1 = dis[to];

	memset(dis, 0, sizeof dis); to = 0;
	maxx = -1, dfs(v, v);
	memset(dis, 0, sizeof dis);
	maxx = -1, dfs(to, to);
	register int len2 = dis[to];

	register int len = max(len1, len2);
	len = max(len, (len1 + 1) / 2 + (len2 + 1) / 2 + 1);
	vis[id] = vis[id ^ 1] = 0;
	return len;
}

int a[ss], cnt;
signed main(){	
	freopen("league.in", "r", stdin);
	freopen("league.out", "w", stdout);
	register int n = read();
	memset(head, 0, sizeof head);
	for(register int i = 1; i <= n - 1; i++){
		register int u = read(), v = read();
		add(u, v);
		add(v, u);
	}
	register int ans = 0x7fffffff;
	for(register int i = 2; i <= tot; i += 2){
		register int len = getlen(i);
		if(len < ans) ans = len, a[cnt = 1] = i / 2;
		else if(len == ans) a[++cnt] = i / 2;
	}
	write(ans), puts("");
	write(cnt), printf(" ");
	for(register int i = 1; i <= cnt; i++)
		write(a[i]), printf(" ");
	puts("");

	register int id = 2 * a[1];
	register int u = edge[id].from;
	register int v = edge[id].to;
	write(u), printf(" "), write(v), printf(" ");
	vis[id] = vis[id ^ 1] = 1;
	memset(dis, 0, sizeof dis); to = 0;
	maxx = -1; dfs(u, u);
	from = to;
	memset(dis, 0, sizeof dis);
	maxx = -1, dfs(to, to);
	register int getdis = dis[to];
	register int depp = -1;
	register int skip = 0;
	if(depp < dep[from]) depp = dep[from], skip = from;
	if(depp < dep[to]) depp = dep[to], skip = to;
	write(jump(skip, getdis + 1 >> 1)), printf(" ");

	memset(dis, 0, sizeof dis); to = 0;
	maxx = -1, dfs(v, v);
	from = to;
	memset(dis, 0, sizeof dis);
	maxx = -1, dfs(to, to);
	getdis = dis[to];
	depp = -1;
	if(depp < dep[from]) depp = dep[from], skip = from;
	if(depp < dep[to]) depp = dep[to], skip = to;
	write(jump(skip, getdis + 1 >> 1)), printf(" ");
	return 0;
}

D.水滴

最简单的一道了吧。。。
然而考场只有可怜巴巴的(40pts)暴力分
尺取法
每次询问当中(O(n))扫一遍
对左右端点进行扩展

Drop
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define min(a, b) (a) < (b) ? (a) : (b)
using namespace std;

inline int read(){
	int x = 0, w = 1;
	char ch = getchar();
	for(; ch > '9' || ch < '0'; ch = getchar()) if(ch == '-') w = -1;
	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
	return x * w;
}

inline void write(register int x){
	if(x < 0) x = ~x + 1, putchar('-');
	if(x > 9) write(x / 10);
	putchar(x % 10 + '0');
}

const int ss = 200005;

int d[ss], cnt[ss], kill[ss];

signed main(){
	freopen("drop.in", "r", stdin);
	freopen("drop.out", "w", stdout);
	register int T = read();
	while(T--){
		register int ans = 0x7fffffff;
		memset(cnt, 0, sizeof cnt);
		memset(kill, 0, sizeof kill);
		register int n = read(), m = read(), q = read();
		for(register int i = 1; i <= n; i++) d[i] = read();
		for(register int i = 1; i <= q; i++){
			register int pos = read();
			kill[pos] = read();
		}
		register int l = 1, r = 1, tmp = 0;
		while(l <= r && r <= n){
			if(++cnt[d[r]] == kill[d[r]]) tmp++;
			while(cnt[d[l]] > kill[d[l]]) cnt[d[l]]--, l++;
			if(tmp == q) ans = min(ans, r - l + 1);
			r++;
		}
		if(ans == 0x7fffffff) puts("DESTROY ALL");
		else write(ans), puts("");
	}
	return 0;
}
原文地址:https://www.cnblogs.com/rui-4825/p/13826371.html