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: 记忆
不会,咕咕。
与你的日常,便是奇迹

浙公网安备 33010602011771号