A
B

NOIP 模拟赛1

NOIP 模拟赛总结

NOIP 模拟赛 1

暴力专场,打了足足 4 个暴力。QwQ

T1 公司的供应链

容易观察到题意可理解为在保证每个点入度与出度和之差不变的前提下,把图中的边全删掉。

直接遍历一遍图,维护一个栈,遇到环直接弹栈即可。

时间复杂度 \(O(n)\)

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define Blue_Archive return 0 
using namespace std;
constexpr int N = 3e5 + 3;
constexpr int M = 6e5 + 3;

int n;
int m;
int tot;
int ans;
int h[N];
int id[M];
int to[M];
int can[N];
int nxt[M];
int tim[N];
int vis[N];

struct miku
{
	int l,r;
}e[M];

struct mika
{
	int id;
	int to;
};

vector<mika> g[N];

inline int dfs(int x)
{
	if(vis[x]) return x;
	vis[x] = 1;
	while(tim[x] < (int)g[x].size())
	{
		int res = dfs(g[x][tim[x]].to);
		can[g[x][tim[x] ++].id] = (!res ? -1 : 1);
		if(res != x && res) return vis[x] = 0,res;
	}
	return vis[x] = 0,0;
}

signed main()
{
	freopen("dag.in","r",stdin);freopen("dag.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 >> n >> m;
	for(int i = 1;i <= m;i ++)
	{
		cin >> e[i].l >> e[i].r;
		g[e[i].l].push_back({i,e[i].r});
	}
	for(int i = 1;i <= n;i ++)
	{
		if(tim[i] < (int)g[i].size())
		{
			dfs(i);
		}
	}
	for(int i = 1;i <= m;i ++) ans += (can[i] < 0);
	cout << ans << '\n';
	for(int i = 1;i <= m;i ++)
	{
		if(can[i] >= 0) continue;
		cout << e[i].l << ' ' << e[i].r << '\n';
	}
	Blue_Archive;
}

T2 宇宙的卷积

不会,只会暴力。

题解说答案只有 \(3 ^ n\) 种,直接预处理即可。

点击查看代码

#include<bits/stdc++.h>
// #define int long long 
#define Blue_Archive return 0
using namespace std;
constexpr int N = 3e5 + 3;

int n;
int k;
int a[N];
int c[N];
int b[20][N];

inline void dfs(int x,int now,int res)
{
	if(x == n)
	{
		for(int i = k - res;;i = (i - 1) & (k - res))
		{
			c[res | i] = max(c[res | i],a[res] + b[now][i]);
			if(!i) break;
		}
		return;
	}
	dfs(x + 1,now,res);
	res |= 1 << x;
	for(int i = k - res;;i = (i - 1) & (k - res))
	{
		b[now + 1][i] = max(b[now][i],b[now][i | 1 << x]);
		if(!i) break;
	}
	dfs(x + 1,now + 1,res);
}

signed main()
{
	freopen("juanji.in","r",stdin);freopen("juanji.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 >> n;
	k = (1 << n) - 1;
	for(int i = 0;i <= k;i ++) cin >> a[i];
	for(int i = 0;i <= k;i ++) cin >> b[0][i];
	dfs(0,0,0);
	for(int i = 0;i <= k;i ++) cout << c[i] << ' ';
	cout << '\n';
	Blue_Archive;
}

T3:舰队的远征

先跑两边最短路,然后直接 DP 即可。

需要斜率优化(但是我忘了,所以直接上一棵 LCT(bushi,其实是李超树qwq) )。

点击查看代码
#include<bits/stdc++.h>
#define int long long 
#define add(u,v,z) to[++ tot] = v,w[tot] = z,nxt[tot] = h[u],h[u] = tot
#define Blue_Archive return 0
using namespace std;
constexpr int N = 2e5 + 3;
constexpr int M = 4e5 + 3;
constexpr int INF = 0x3f3f3f3f3f3f3f3f;

int n;
int m;
int st;
int ed;
int ans;
int tot;
int h[N];
int w[M];
int to[M];
int nxt[M];
int dis1[N];
int dis2[N];

bool vis[N];

vector<int> vec1,vec2;
vector<pair<int,int>> e[N];

priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> q;

inline void dijk()
{
	memset(dis1,0x3f,sizeof(dis1));
	q.push({0,st});
	dis1[st] = 0;
	while(!q.empty())
	{
		int u = q.top().second;
		q.pop();
		if(vis[u]) continue;
		vis[u] = 1;
		for(int i = h[u];i;i = nxt[i])
		{
			if(dis1[to[i]] > dis1[u] + w[i])
			{
				dis1[to[i]] = dis1[u] + w[i];
				q.push({dis1[to[i]],to[i]});
			} 
		}
	}
}

inline void dij()
{
	memset(dis2,0x3f,sizeof(dis2));
	memset(vis,0,sizeof(vis));
	q.push({0,ed});
	dis2[ed] = 0;
	while(!q.empty())
	{
		int u = q.top().second;
		q.pop();
		if(vis[u]) continue;
		vis[u] = 1;
		for(pair<int,int> op : e[u])
		{
			if(dis2[op.first] > dis2[u] + op.second)
			{
				dis2[op.first] = dis2[u] + op.second;
				q.push({dis2[op.first],op.first});
			} 
		}
	}
}


struct LiChao_Tree
{
	int s[N << 2];

	struct miku
	{
		int k,b;
	}p[N];

	#define lid (id << 1)
	#define rid (id << 1 | 1)
	#define calc(id,d) (p[id].b + p[id].k * d)

	inline void ins(int id,int l,int r,int u)
	{
		if(!s[id]) return void(s[id] = u);
		if(l == r)
		{
			if(calc(s[id],l) > calc(u,l)) s[id] = u;
			return;
		}
		int mid = (l + r) >> 1;
		if(calc(u,mid) < calc(s[id],mid)) swap(s[id],u);
		if(calc(u,l) < calc(s[id],l)) ins(lid,l,mid,u);
		if(calc(u,r) < calc(s[id],r)) ins(rid,mid+1,r,u);
	}

	inline int query(int id,int l,int r,int pos)
	{
		if(l == r) return calc(s[id],pos);
		int res = calc(s[id],pos);
		int mid = (l + r) >> 1;
		if(pos <= mid) res = min(res,query(lid,l,mid,pos));
		else res = min(res,query(rid,mid + 1,r,pos));
		return res;
	}
}LCT; // zhe shi li chao shu


signed main()
{
	freopen("far.in","r",stdin);freopen("far.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 >> n >> m >> st >> ed;
	for(int i = 1,x,y,z;i <= m;i ++)
	{
		cin >> x >> y >> z;
		add(x,y,z);
		e[y].push_back({x,z});
	}
	dijk();
	dij();
	LCT.p[0] = {0,INF};
	for(int i = 1;i <= n;i ++)
	{
		LCT.p[i].k = -2 * i;
		LCT.p[i].b = i * i + dis2[i];
		LCT.ins(1,1,n,i);
	}
	ans = (st - ed) * (st - ed);
	for(int i = 1;i <= n;i ++) ans = min(ans,LCT.query(1,1,n,i) + i * i + dis1[i]);
	cout << ans << '\n';
	Blue_Archive;
}

T4:军团的阵列线

扫描线,但是我没改,不太会。qwq

posted @ 2025-11-14 08:26  MyShiroko  阅读(17)  评论(0)    收藏  举报