A
B

NOIP 模拟赛 9

NOIP 模拟赛总结

NOIP 模拟赛 9

调了一整场的 T2,样例全过!只有 40 pts。QxQ

T1 卡门

连续两场 T1 放数据结构了欸

数据结构题,直接分块就行。

赛时没算时间复杂度,导致打了个暴力交上去以为是正解。

赛后半小时改完,挂挂挂!

点击查看代码
#include <stdio.h>
#include <vector>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <cmath>
#define con putchar_unlocked(' ')
#define ent putchar_unlocked('\n')
#define Blue_Archive return 0
using namespace std;
constexpr int N = 3e4 + 3;
constexpr int B = 175;
constexpr int M = 31;
constexpr int me = 0x0d000721;

int n;	
int m;
int K;
int ans;
int len;
int L[B];
int R[B];
int id[N];

pair<int,int> to[B][M];

int mp[N][M];

inline void dfs_init(int x,int y,int dep,pair<int,int>&op)
{
	if(x == dep) return void(op = {x,y});
	if(!mp[x + 1][y]) dfs_init(x + 1,y,dep,op);
	else if(mp[x + 1][y] == 2)
	{
		if(y > 1 && !mp[x][y - 1] && !mp[x + 1][y - 1]) dfs_init(x,y - 1,dep,op);
		else if(y < m && !mp[x][y + 1] && !mp[x + 1][y + 1]) dfs_init(x,y + 1,dep,op);
		else return void(op = {x,y});
	}
	else return void(op = {x,y});
}

inline void init()
{
	int len = sqrt(n);
	for(int i = 1;i <= n;i ++)
	{
		id[i] = (i - 1) / len + 1;
		if(!L[id[i]]) L[id[i]] = i;
		R[id[i]] = i;
	}
	for(int i = 1;i < id[n];i ++)
	{
		for(int j = 1;j <= m;j ++)
		{
			dfs_init(L[i],j,R[i] + 1,to[i][j]);
		}
	}
	for(int i = 1;i <= m;i ++) dfs_init(L[id[n]],i,n,to[id[n]][i]);
}

inline void query(int x)
{
	int now = x;
	int op = 0;
	for(int i = 1;i <= id[n];i ++)
	{
		if(to[i][now].first != R[i] + 1) break;
		op = i;
		now = to[i][now].second;
	}
	op ++;
	mp[to[op][now].first][to[op][now].second] = 2;
	if(to[op][now].first == L[op])
	{
		for(int i = 1;i <= m;i ++)
		{
			if(to[op - 1][i].first == L[op] && to[op - 1][i].second == to[op][now].second) dfs_init(L[op - 1],i,R[op - 1] + 1,to[op - 1][i]);
		}
	}
	for(int i = 1;i <= m;i ++)
	{
		dfs_init(L[op],i,min(R[op] + 1,n),to[op][i]);
	}
}

signed main()
{
	freopen("kamen.in","r",stdin);freopen("kamen.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;
	char op;
	for(int i = 1;i <= n;i ++)
	{
		for(int j = 1;j <= m;j ++)
		{
			cin >> op;
			mp[i][j] = (op == '.') ? 0 : 1;
		}
	}
	init();
	cin >> K;
	for(int i = 1,x;i <= K;i ++)
	{
		cin >> x;
		query(x);
	}
	for(int i = 1;i <= n;i ++)
	{
		for(int j = 1;j <= m;j ++)
		{
			if(mp[i][j] == 0) cout << '.';
			else if(mp[i][j] == 1) cout << 'X';
			else if(mp[i][j] == 2) cout << 'O';
		}
		cout << '\n';
	}
	Blue_Archive;
}

T2 商人

5 个样例全过,只得 40 pts,qwq。

考虑建反图。

发现每个在环上的点都会对其他点造成贡献。

所以朴素想法是对于每个环上的点跑一遍最短路。

但是这样显然会 TLE。

所以考虑贪心地去做,将每条边离线后按照 \(r\) 值从小往大排序。

然后考虑每一条边的贡献,详细地说,就是对于每一条边来说,如果删掉这条边将会把一个环点断成非环点,那么将该点压入队列更新其他点的答案。

如果在更新答案时遍历过了这条边,那么直接跳过(因为该边的贡献已经被计入答案)。

这样的话,时间复杂度为 \(O(m \log{m})\)

点击查看代码
#include <stdio.h>
#include <vector>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <bitset>
#include <queue>
#define int long long 
#define add(u,v) to[++ tot] = v,nxt[tot] = h[u],h[u] = tot
#define con putchar_unlocked(' ')
#define ent putchar_unlocked('\n')
#define Blue_Archive return 0
using namespace std;
constexpr int N = 2e5 + 3;
constexpr int me = 0x0d00721;
constexpr int INF = 1e9;

int n;
int m;
int tot;
int h[N];
int in[N];
int to[N];
int nxt[N];
int ans[N];

bitset<N> vis;

queue<int> q;

struct miku
{
	int x,y,r,p;
	friend bool operator < (miku a,miku b){return a.r < b.r;}
}eg[N];

signed main()
{
	freopen("merchant.in","r",stdin);freopen("merchant.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,x,y,r,p;i <= m;i ++)
	{
		cin >> x >> y >> r >> p;
		eg[i] = {x,y,r,p};
		in[x] ++;
	}
	memset(ans,0x3f,sizeof(ans));
	sort(eg + 1,eg + m + 1);
	for(int i = 1;i <= m;i ++) add(eg[i].y,i);
	for(int i = 1;i <= n;i ++) if(!in[i]) q.push(i);
	for(int i = m;i >= 1;i --)
	{
		while(!q.empty())
		{
			int u = q.front();
			q.pop();
			for(int j = h[u];j;j = nxt[j])
			{
				if(vis[to[j]]) continue;
				vis[to[j]] = 1;
				-- in[eg[to[j]].x];
				if(!in[eg[to[j]].x]) q.push(eg[to[j]].x);
				if(ans[u] < INF) ans[eg[to[j]].x] = min(ans[eg[to[j]].x],max(eg[to[j]].r,ans[u] - eg[to[j]].p));
			}
		}
		if(!vis[i])
		{
			vis[i] = 1;
			-- in[eg[i].x];
			if(!in[eg[i].x]) q.push(eg[i].x);
			ans[eg[i].x] = min(ans[eg[i].x],eg[i].r);
		}
	}
	for(int i = 1;i <= n;i ++) cout << ((ans[i] > INF) ? -1 : ans[i]) << ' ';
	Blue_Archive;
}

T3:自行车

不会,咕咕。

T4: 记忆

不会,咕咕。

posted @ 2025-11-17 22:11  MyShiroko  阅读(32)  评论(0)    收藏  举报