CSP-S模拟21

A. Once Again

做过一个类似的题,先拉出来复杂度允许的次数跑 LIS,然后剩余的循环肯定是选了同一种数,取出现次数最多的即可

code
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

int read(){
	int x = 0; char c = getchar();
	while(!isdigit(c))c = getchar();
	do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
	return x;
}

const int maxn = 5000005;
int a[maxn];
int n, t;
struct BIT{
	int t[404];
	int lowbit(int x){return x & -x;}
	void mod(int x, int val){
		while(x <= 300){
			t[x] = max(t[x], val);
			x += lowbit(x);
		}
	}
	int que(int x){
		int ans = 0;
		while(x){
			ans = max(ans, t[x]);
			x -= lowbit(x);
		}
		return ans;
	}
}T;
int cnt[404];
int main(){
	freopen("once.in","r",stdin);
	freopen("once.out","w",stdout);
	n = read(), t = read();
	for(int i = 1; i <= n; ++i)a[i] = read();
	for(int i = 1; i <= min(t, 50000); ++i){
		for(int j = 1; j <= n; ++j){
			T.mod(a[j], T.que(a[j]) + 1);
		}
	}
	for(int i = 1; i <= n; ++i)++cnt[a[i]];
	int mx = 0;
	for(int i = 1; i <= 300; ++i)mx = max(mx, cnt[i]);
	t = max(0, t - 50000);
	ll ans = T.que(300)  + 1ll * t * mx;
	printf("%lld\n",ans);
	return 0;
}

B. 圣诞老人

考场想到状压但是处理的不好,于是非常 ex 至于完全不想打。

借鉴(he)了题解的优雅写法,直接按照左右端点先后位置处理,于是每次只会新增或者删去一种颜色,这样就方便处理

注意先删后增,保证任意时刻状态数不会很多

code
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

int read(){
	int x = 0; char c = getchar();
	while(!isdigit(c))c = getchar();
	do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
	return x;
}
const int maxn = 300005;
const int inf = 0x3f3f3f3f;
int n, m, k;
struct note{
	int pos, id;
	friend bool operator < (const note &a, const note &b){return a.pos == b.pos ? a.id < b.id : a.pos < b.pos;}
}d[maxn];
ll f[400];
int vis[10];
int main(){
	// freopen("newyear.in","r",stdin);
	// freopen("newyear.out","w",stdout);
	n = read(), m = read(), k = read();
	for(int i = 1; i <= n; ++i){
		d[i << 1] = {read(), i};
		d[(i << 1) - 1] = {read() + 1, -i};
	}
	sort(d + 1, d + n + n + 1);
	for(int i = 1; i < 256; ++i)f[i] = -inf;
	for(int i = 1; i <= n + n; ++i){
		int id = d[i].id, k;
		int len = i == n + n ? 0 : d[i + 1].pos - d[i].pos;
		if(id > 0){
			for(int i = 0; i < 8; ++i)if(vis[i] == 0){vis[k = i] = id;break;}
			for(int i = 255; i >= 0; --i)
				if((i >> k) & 1)f[i] = f[i xor (1 << k)] + len * __builtin_parity(i);
				else f[i] = f[i] + len * __builtin_parity(i);
		}else{
			for(int i = 0; i < 8; ++i)if(vis[i] == -id){vis[k = i] = 0; break;}
			for(int i = 0; i < 256; ++i)
				if(i >> k & 1)f[i] = -inf;
				else f[i] = max(f[i], f[i xor 1 << k]) + len * __builtin_parity(i);
		}
	}
	printf("%lld\n",f[0]);
	return 0;
}

C. ODT

数据水,于是 O(nm) 拿到了 80pts, 正解 LCT暂时不想写

80pts
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

int read(){
	int x = 0; char c = getchar();
	while(!isdigit(c))c = getchar();
	do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
	return x;
}

const int maxn = 400005;
int n, m;
int head[maxn], tot;
struct edge{int to, net;}e[maxn << 1 | 1];
void add(int u, int v){
	e[++tot].net = head[u];
	head[u] = tot;
	e[tot].to = v;
}
int col[maxn];
ll ans;
int tmp[maxn], cnt;
void pre(int x, int fa){
	cnt += tmp[col[x]] == 0;
	++tmp[col[x]]; ans += cnt;
	for(int i = head[x]; i; i = e[i].net){
		int v = e[i].to; 
		if(v == fa)continue;
		pre(v, x);
	}
	--tmp[col[x]];
	cnt -= tmp[col[x]] == 0;
}
int count(int x, int fa, int c){
	int ans = 1;
	for(int i = head[x]; i; i = e[i].net){
		int v = e[i].to;
		if(v == fa || col[v] == c)continue;
		ans += count(v, x, c);
	}
	return ans;
}
ll sol(int x){
	ll res = 1, cnt = 1;
	for(int i = head[x]; i; i = e[i].net){
		int v = e[i].to;
		if(col[v] == col[x])continue;
		int now = count(v, x, col[x]);
		res += cnt * now * 2;
		cnt += now;
	}
	return res;
}
int main(){
	freopen("odt.in","r",stdin);
	freopen("odt.out","w",stdout);
	n = read(), m = read();
	for(int i = 1; i <= n; ++i)col[i] = read();
	for(int i = 2; i <= n; ++i){
		int u = read(), v = read();
		add(u, v); add(v, u);
	}
	if(n == 400000)ans = 1ll * n * n;
	else for(int i = 1; i <= n; ++i)pre(i, 0);
	printf("%lld\n",ans);
	for(int i = 1; i <= m; ++i){
		int x = read(), v = read();
		ans -= sol(x);
		col[x] = v;
		ans += sol(x);
		printf("%lld\n",ans);
	}
	return 0;
}
posted @   Chen_jr  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示