A
B

NOIP 模拟赛 5

NOIP 模拟赛总结

NOIP 模拟赛 5

挂分啦

T1 家具运输

简单签到题,一眼二分答案。

点击查看代码
#include<bits/stdc++.h>
#define int long long 
#define Blue_Archive return 0
#define con putchar_unlocked(' ')
#define ent putchar_unlocked('\n')
using namespace std;
constexpr int N = 2e3 + 7;
constexpr int INF = 1e18;

int n;
int K;
int sum;
int a[N];

bitset<N> vis;

inline int read()
{
	int x = 0,f = 1;
	int c = getchar_unlocked();
	while(c < '0' || c > '9') f = (c == '-' ? -1 : f),c = getchar_unlocked();
	while(c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48),c = getchar_unlocked();
	return x * f;
}

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

inline bool check(int op)
{
	int tot = 0;
	vis.reset();
	for(int i = 1,res;i <= K;i ++)
	{
		res = op;
		for(int j = 1;j <= n;j ++)
		{
			if(vis[j] || a[j] > res) continue;
			res -= a[j];
			tot ++;
			vis[j] = 1;
		}
	}
	return (tot == n);
}

signed main()
{
	freopen("trans.in","r",stdin);freopen("trans.out","w",stdout);
	// freopen("data.in","r",stdin);freopen("data.out","w",stdout);
	n = read();
	K = read();
	for(int i = 1;i <= n;i ++)
	{
		a[i] = read();
		sum += a[i];
	} 
	sort(a + 1,a + n + 1,[](int a,int b){return a > b;});
	int l = sum / K,r = sum,mid,res = -1;
	while(l <= r)
	{
		mid = (l + r) >> 1;
		if(check(mid)) r = mid - 1,res = mid;
		else l = mid + 1;
	}
	write(res);ent;
	Blue_Archive;
}

T2 取石子

神秘博弈论。

发现与二进制有关,要满足进行操作后使对方陷入无解的境地。

然后狂找性质不止。

点击查看代码
#include<bits/stdc++.h>
#define int long long 
#define Blue_Archive return 0
#define con putchar_unlocked(' ')
#define ent putchar_unlocked('\n')
using namespace std;
constexpr int N = 5e4 + 7;
constexpr int M = 2e6 + 7;
constexpr int INF = 1e18;

int n;
int K;
int sum;
int a[N];

bool flag;

inline int read()
{
	int x = 0,f = 1;
	int c = getchar_unlocked();
	while(c < '0' || c > '9') f = (c == '-' ? -1 : f),c = getchar_unlocked();
	while(c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48),c = getchar_unlocked();
	return x * f;
}

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

signed main()
{
	freopen("nim.in","r",stdin);freopen("nim.out","w",stdout);
	// freopen("data.in","r",stdin);freopen("data.out","w",stdout);
	n = read();
	K = read();
	for(int i = 1;i <= n;i ++)
	{
		a[i] = read();
		sum ^= a[i];
	} 
	for(int i = 1;i <= n;i ++)
	{
		for(int j = 1,now = 0,op;;j <<= 1)
		{
			if(now + j > a[i] || now + j > K) break;
			op = a[i] - now; // 还剩这些
			if(((sum ^ a[i] ^ op) & j) && ((sum ^ (op - j) ^ a[i]) & (j - 1)) == 0) // ((sum ^ (op - j) ^ a[i]) & (j - 1)) == 0 指让变化之后其他位的均为 0,使对方无解。 
			{
				if(!flag)
				{
					write(1);ent;
					flag = 1;
				}
				now += j;
				write(i),con,write(now),ent;
			}
		}
	}
	if(!flag) write(0),ent;
	Blue_Archive;
}

T3:均衡区间

只会 \(O(n ^ 2)\) 暴力qwq,SAM 场上根本手摸不出来qwq

发现不需要用 SA or SAM,直接在 fail 树上做树形 DP 即可。

点击查看代码
#include<bits/stdc++.h>
#define int long long 
#define add(u,v) to[++ tot] = v,nxt[tot] = h[u],h[u] = tot
#define ull unsigned long long 
#define Blue_Archive return 0
#define con putchar_unlocked(' ')
#define ent putchar_unlocked('\n')
using namespace std;
constexpr int N = 1e6 + 7;
constexpr int M = 1e6 + 7;
constexpr int INF = 1e18;
constexpr int mod = 998244353;

int n;
int K;
int ans;
int res;
int tot;
int a[N];
int h[N];
int to[M];
int nxt[M];
int fac[N];
int inv[N];
int siz[N];
int qnxt[N];

string s;

inline int qpow(int a,int b)
{
	int res = 1;
	while(b)
	{
		if(b & 1) res = res * a % mod;
		a = a * a % mod;
		b >>= 1;
	}
	return res;
}

inline void init()
{
	fac[0] = inv[0] = 1;
	for(int i = 1;i < N;i ++)
	{
		fac[i] = fac[i - 1] * i % mod;
		inv[i] = qpow(fac[i],mod - 2);
	} 
}

inline int C(int n,int m)
{
	if(n < m) return 0;
	return fac[n] * inv[n - m] % mod * inv[m] % mod;
}
int op = 0;
inline void dfs(int x,int dep)
{
	siz[x] = 1;
	for(int i = h[x];i;i = nxt[i])
	{
		dfs(to[i],dep + 1);
		siz[x] += siz[to[i]];
		a[x] = ((a[x] - C(siz[to[i]],K) * dep % mod * dep % mod + a[to[i]]) % mod + mod) % mod;
	}
	a[x] = (a[x] + dep * dep % mod * C(siz[x],K) % mod) % mod;
}

signed main()
{
	freopen("string.in","r",stdin);freopen("string.out","w",stdout);
	// freopen("data.in","r",stdin);freopen("data.out","w",stdout);
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin >> K;
	cin >> s;
	n = s.length();
	s = ' ' + s;
	init();
	add(0,1);
	for(int i = 2,j = 0;i <= n;i ++)
	{
		while(j && s[i] != s[j + 1]) j = qnxt[j];
		if(s[i] == s[j + 1]) j ++;
		qnxt[i] = j;
		add(qnxt[i],i);
	}
	dfs(0,1);
	ans = a[0];
	cout << ans << '\n';
	Blue_Archive;
}

T4:蚂蚁搬家

简单题,赛时因为线段树写假了 + 多开了 O(n) 个 set,导致 MLE。

进食后人,laz 标记千万不要忘记下放,痛挂 100 pts。qwq

点击查看代码
#include<bits/stdc++.h>
// #define int long long 
#define ull unsigned long long 
#define lid (id << 1)
#define rid (id << 1 | 1)
#define add(u,v) to[++ tot] = v,nxt[tot] = h[u],h[u] = tot
#define Blue_Archive return 0
#define con putchar_unlocked(' ')
#define ent putchar_unlocked('\n')
using namespace std;
constexpr int N = 1e6 + 7;
constexpr int M = 2e6 + 7;
constexpr int INF = 1e9;

int n;
int tot;
int tim;
int a[N];
int h[N];
int to[M];
int rk[N];
int fa[N];
int nxt[M];
int dep[N];
int son[N];
int siz[N];
int dfn[N];
int top[N];

unordered_map<ull,int> mp;

struct miku
{
	int mn,id;
	int laz;
	ull bel,laz1,laz2;
}tr[N << 2];

struct mika
{
	int u,v;
	ull hx;
}q[N];

inline int read()
{
	int x = 0,f = 1;
	int c = getchar_unlocked();
	while(c < '0' || c > '9') f = (c == '-' ? -1 : f),c = getchar_unlocked();
	while(c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48),c = getchar_unlocked();
	return x * f;
}

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

inline void dfs1(int x,int f)
{
	dep[x] = dep[f] + 1;
	fa[x] = f;
	siz[x] = 1;
	for(int i = h[x];i;i = nxt[i])
	{
		if(to[i] == f) continue;
		dfs1(to[i],x);
		siz[x] += siz[to[i]];
		if(siz[to[i]] > siz[son[x]]) son[x] = to[i];
	}
}

inline void dfs2(int x,int tp)
{
	top[x] = tp;
	dfn[x] = ++ tim;
	if(son[x]) dfs2(son[x],tp);
	for(int i = h[x];i;i = nxt[i])
	{
		if(to[i] == son[x] || to[i] == fa[x]) continue;
		dfs2(to[i],to[i]);
	}
}

inline void pushup(int id)
{
	tr[id].mn = min(tr[lid].mn,tr[rid].mn);
	tr[id].id = (tr[lid].mn == tr[id].mn) ? tr[lid].id : tr[rid].id;
}

inline void change(int id,int cnt,int val)
{
	tr[id].mn += cnt;
	tr[id].laz += cnt;
	tr[id].bel ^= val;
	if(cnt > 0) tr[id].laz1 ^= val;
	else tr[id].laz2 ^= val;
}

inline void pushdown(int id)
{
	if(!tr[id].laz) return;
	if(tr[id].laz > 0)
	{
		change(lid,tr[id].laz,tr[id].laz1);
		change(rid,tr[id].laz,tr[id].laz1);
		tr[id].laz1 = 0;
	} 
	else
	{
		change(lid,tr[id].laz,tr[id].laz2);
		change(rid,tr[id].laz,tr[id].laz2);
		tr[id].laz2 = 0;
	} 
	tr[id].laz = 0;
}

inline void build(int id,int l,int r)
{
	if(l == r) return void(tr[id].id = l);
	int mid = (l + r) >> 1;
	build(lid,l,mid);
	build(rid,mid + 1,r);
	pushup(id);
}

inline void update(int id,int l,int r,int L,int R,int val,ull uid)
{
	if(L > r || l > R || L > R) return;
	if(L <= l && r <= R)
	{
		change(id,val,uid);
		return;
	}
	int mid = (l + r) >> 1;
	pushdown(id);
	update(lid,l,mid,L,R,val,uid);
	update(rid,mid + 1,r,L,R,val,uid);
	pushup(id);
}

inline ull query(int id,int l,int r,int pos)
{
	if(l == r) return tr[id].bel;
	int mid = (l + r) >> 1;
	pushdown(id);
	if(pos <= mid) return query(lid,l,mid,pos);
	else return query(rid,mid + 1,r,pos);
	pushup(id);
}

inline int query_mn(int id,int l,int r,int pos)
{
	if(l == r) return tr[id].mn;
	int mid = (l + r) >> 1;
	pushdown(id);
	if(pos <= mid) return query_mn(lid,l,mid,pos);
	else return query_mn(rid,mid + 1,r,pos);
}

inline void build2(int id,int l,int r)
{
	if(l == r) return;
	if(tr[id].mn == 0) tr[id].mn = INF;
	pushdown(id);
	int mid = (l + r) >> 1;
	build2(lid,l,mid);
	build2(rid,mid + 1,r);
	pushup(id);
}

inline void path_add(int u,int v,ull id)
{
	while(top[u] != top[v])
	{
		if(dep[top[u]] < dep[top[v]]) swap(u,v);
		update(1,1,n,dfn[top[u]],dfn[u],1,id);
		u = fa[top[u]];
	}
	if(dep[u] > dep[v]) swap(u,v);
	update(1,1,n,dfn[u]+1,dfn[v],1,id);
}

inline void path_del(int u,int v,ull id)
{
	while(top[u] != top[v])
	{
		if(dep[top[u]] < dep[top[v]]) swap(u,v);
		update(1,1,n,dfn[top[u]],dfn[u],-1,id);
		u = fa[top[u]];
	}
	if(dep[u] > dep[v]) swap(u,v);
	update(1,1,n,dfn[u] + 1,dfn[v],-1,id);
}

signed main()
{
	freopen("ants.in","r",stdin);freopen("ants.out","w",stdout);
	// freopen("data.in","r",stdin);freopen("data.out","w",stdout);
	n = read();
	for(int i = 1,u,v;i < n;i ++)
	{
		u = read();
		v = read();
		add(u,v);
		add(v,u);
	}
	dfs1(1,0);
	dfs2(1,1);
	build(1,1,n);
	update(1,1,n,1,1,INF,INF);
	for(int i = 1;i < n;i ++)
	{
		q[i].u = read();
		q[i].v = read();
		q[i].hx = i;
		mp[q[i].hx] = i;
		path_add(q[i].u,q[i].v,q[i].hx);
	}
	build2(1,1,n);
	ull pos;
	for(int i = 1;i < n;i ++)
	{
		if(tr[1].mn != 1){puts("NO");exit(0);}
		pos = query(1,1,n,tr[1].id);
		if(!mp.count(pos)){puts("NO");exit(0);}
		path_del(q[mp[pos]].u,q[mp[pos]].v,pos);
		update(1,1,n,tr[1].id,tr[1].id,INF,INF);
	}
	puts("YES");
	Blue_Archive;
}
posted @ 2025-11-14 08:27  MyShiroko  阅读(11)  评论(0)    收藏  举报