NOIP2024模拟1
rank 6,T1 59,T2 50,T3 50,T4 0
打了三道搜索。T4 树套树没调出来就结束了香雪还没写,遗憾离场。
玩游戏
贪心,只会暴力跳……
点此查看代码
#include<bits/stdc++.h>
using namespace std;
#define rep(i,s,t,p) for(int i = s;i <= t; i += p)
#define drep(i,s,t,p) for(int i = s;i >= t; i -= p)
#ifdef LOCAL
FILE *InFile = freopen("in.in","r",stdin),*OutFile = freopen("out.out","w",stdout);
#else
FILE *InFile = stdin,*OutFile = stdout;
#endif
using ll=long long;using ull=unsigned long long;
using db = double;using ldb = long double;
#define int long long
const int N = 1e5 + 10;
int n,k,a[N],sum[N];
inline void solve(){
rep(i,1,n,1) sum[i] = 0;
bool flag = false;
cin>>n>>k;int r = k;rep(i,1,n,1) cin>>a[i];
drep(j,k-1,1,1) sum[j] = sum[j + 1] + a[j + 1];
rep(j,k+1,n,1) sum[j] = sum[j - 1] + a[j];
drep(j,k,1,1){
while(sum[r + 1] + sum[j] <= 0 && r < n) r++;
while(sum[r] + sum[j] > 0 && r > 0) r--;
if(r < k){flag = true;break;}
}
if((!flag) && r == n) cout<<"Yes\n";
else cout<<"No\n";
}
signed main(){
cin.tie(nullptr)->sync_with_stdio(false);
int T;cin >> T; while(T--) solve();
}
排列
笛卡尔树上dp,不会……
最短路
写了个搜索+剪枝,过了大样例,能拿50比较牛。然而事实是只加一个最优性剪枝就过了,时间复杂度\(O(能过OJ的水数据)\),当然,这是错的。挂个好不容易才卡出来的。
点此查看代码
#include<bits/stdc++.h>
using namespace std;
#define rep(i,s,t,p) for(int i = s;i <= t; i += p)
#define drep(i,s,t,p) for(int i = s;i >= t; i -= p)
#ifdef LOCAL
FILE *InFile = freopen("in.in","r",stdin),*OutFile = freopen("out.out","w",stdout);
// FILE *ErrFile = freopen("err.err","w",stderr);
#else
FILE *InFile = stdin,*OutFile = stdout;
#endif
using ll=long long;using ull=unsigned long long;
using db = double;using ldb = long double;
#define eb emplace_back
const int N = 256;
vector<int> e[N];
int n,m,p[N],ans = 0x3f3f3f3f,tot = 0,dist[N],fa[N];
vector<int> ch;
bitset<N> vis,rvis;
#define pii pair<int,int>
#define mk make_pair
inline bool dijkstra(int s,int t){
priority_queue<pii,vector<pii>,greater<pii> > q;
memset(dist,0x3f,sizeof dist);memset(fa,0,sizeof fa);
dist[s] = p[s];
q.push(mk(dist[s],s));
bitset<N> vis;
while(q.size()){
int x = q.top().second;q.pop();
if(vis[x]) continue;
vis[x] = true;
for(int y:e[x]){
if(dist[y] > dist[x] + p[y]){
dist[y] = dist[x] + p[y];
fa[y] = x;
q.push(mk(dist[y],y));
}
}
}
int x = t;while(x) ch.emplace_back(x),x = fa[x];
return vis[t];
}
void rdfs(int x){
rvis[x] = true;
if(!vis[x]) tot += p[x];
if(tot < ans){
if(x == 1) ans = min(ans,tot);
else{
for(int y:e[x]){
if(rvis[y]) continue;
rdfs(y);
}
}
}
if(!vis[x]) tot -= p[x];
rvis[x] = false;
}
void dfs(int x){
vis[x] = true;
tot += p[x];
if(tot < ans){
if(x == n){rvis.reset();rdfs(n);}
else{
for(int y:e[x]){
if(vis[y]) continue;
dfs(y);
}
}
}
tot -= p[x];
vis[x] = false;
}
inline void solve(){
cin>>n>>m;rep(i,1,n,1) cin>>p[i];
rep(i,1,m,1){int u,v;cin>>u>>v;e[u].eb(v);}
bool flag = dijkstra(1,n)&dijkstra(n,1);
if(!flag) return cout<<"-1",void();
sort(ch.begin(),ch.end());ch.erase(unique(ch.begin(),ch.end()),ch.end());
ans = 0;
for(auto i:ch) ans += p[i];
dfs(1);cout<<ans;
}
signed main(){
cin.tie(nullptr)->sync_with_stdio(false);
solve();
}
正解是dp,考虑\(n\rightarrow 1\)的路径一定是往回走一段和沿着\(1\rightarrow n\)的路径走一段交替。
\(f_{i,j}\)表示走\(1\rightarrow n\),从\(i\rightarrow j\)的最小花费。
\(g_{i,j}\)表示走\(n\rightarrow 1\),从\(i\rightarrow j\)的最小花费。
用最短路转移即可,这里将二维压成一维了然后喜提最裂解
点此查看代码
#include<bits/stdc++.h>
using namespace std;
#define rep(i,s,t,p) for(int i = s;i <= t; i += p)
#define drep(i,s,t,p) for(int i = s;i >= t; i -= p)
#ifdef LOCAL
FILE *InFile = freopen("in.in","r",stdin),*OutFile = freopen("out.out","w",stdout);
#else
FILE *InFile = stdin,*OutFile = stdout;
#endif
using ll=long long;using ull=unsigned long long;
using db = double;using ldb = long double;
#define pii pair<int,int>
#define mk make_pair
#define eb emplace_back
const int N = 260,inf = 0x3f3f3f3f;
int n,m,dist[150010],p[N],d[N][N];
vector<pii> g[150010];
inline void add(int u,int v,int w){g[u].push_back(mk(v,w));}
inline int getp(int x,int y,int n){return (x-1)*n+y;}
inline void dijkstra(int s){
bitset<150010> vis;memset(dist,0x3f,sizeof dist);
priority_queue<pii,vector<pii>,greater<pii> > q;
dist[s] = 0;q.push(mk(dist[s],s));
while(q.size()){
int x = q.top().second;q.pop();
if(vis[x]) continue;
vis[x] = true;
for(auto i:g[x])
if(dist[i.first] > dist[x] + i.second){
dist[i.first] = dist[x] + i.second;
q.push(mk(dist[i.first],i.first));
}
}
}
set<pii> st;
inline void solve(){
cin>>n>>m;memset(d,0x3f,sizeof d);
rep(i,1,n,1) cin>>p[i],d[i][i] = 0;
rep(i,1,m,1){
int u,v;cin>>u>>v;d[u][v] = min(d[u][v],p[v]);
if(st.count(mk(u,v))) assert(0);
st.insert(mk(u,v));
}
rep(k,1,n,1) rep(i,1,n,1){
if(i == k) continue;
if(d[i][k] == inf) continue;
rep(j,1,n,1){
if(i == j || j == k || d[i][k] == inf || d[k][j] == inf) continue;
d[i][j] = min(d[i][j],d[i][k] + d[k][j]);
}
}
int ct = 0;
rep(i,1,n,1) rep(j,1,n,1) rep(k,1,n,1){
if(d[j][k] != inf && j != k)
add(getp(i,j,n),getp(k,i,n)+n*n,d[j][k]-p[k]),ct++;
if(d[i][k] != inf && d[k][j] != inf)
add(getp(i,j,n)+n*n,getp(i,k,n),d[i][k] + d[k][j]),ct++;
}
dijkstra(getp(n,n,n));
cout<<(dist[getp(1,1,n)]==inf?-1:dist[getp(1,1,n)]+p[1])<<'\n';
}
signed main(){
cin.tie(nullptr)->sync_with_stdio(false);
solve();
}
矩形
学习的fengwu学长做法。
将矩阵按横坐标排序,挂扫描线,用下边界更新并查集,插入上边界。
点此查看代码
#include<bits/stdc++.h>
using namespace std;
#define rep(i,s,t,p) for(int i = s;i <= t; i += p)
#define drep(i,s,t,p) for(int i = s;i >= t; i -= p)
#ifdef LOCAL
FILE *InFile = freopen("in.in","r",stdin),*OutFile = freopen("out.out","w",stdout);
#else
FILE *InFile = stdin,*OutFile = stdout;
#endif
using ll=long long;using ull=unsigned long long;
using db = double;using ldb = long double;
const int N = 1e5 + 10;
int n;
struct DSU{
vector<int> fa;
inline void init(int n){fa.resize(n+1);rep(i,1,n,1) fa[i] = i;}
inline int get_fa(int x){while(x ^ fa[x]) x = fa[x] = fa[fa[x]];return x;}
inline void Merge(int x,int y){
x = get_fa(x),y = get_fa(y);
if(x == y) return;fa[x] = y;
}
}dsu;
struct Segment_Tree{
struct segment_tree{
int l,r,lz,val,now,up;
#define l(x) tree[x].l
#define r(x) tree[x].r
#define lz(x) tree[x].lz
#define val(x) tree[x].val
#define now(x) tree[x].now
#define up(x) tree[x].up
}tree[N<<2];
inline void P(int k){
int ls = k<<1,rs = k<<1|1;
if(val(ls) == 2 || val(rs) == 2) val(k) = 2;
else if(now(ls) == now(rs)) now(k) = now(ls),up(k) = up(ls),val(k) = 1;
else val(k) = 2;
}
void B(int k,int l,int r){
l(k) = l,r(k) = r,val(k) = 1;
if(l == r) return;
int mid = (l + r) >> 1;
B(k<<1,l,mid);B(k<<1|1,mid+1,r);
}
inline void D(int k){
if(lz(k)){
int ls = k<<1,rs = k<<1|1;
lz(ls) = lz(rs) = lz(k);
now(ls) = now(rs) = now(k);
up(ls) = up(rs) = up(k);
lz(k) = 0;
}
}
void ins(int k,int l,int r,int up,int id){
if(l <= l(k) && r(k) <= r && val(k) == 1){
if(up(k) < up) up(k) = up,now(k) = id,lz(k) = 1;
return;
}
D(k);int mid = (l(k) + r(k)) >> 1;
if(l <= mid) ins(k<<1,l,r,up,id);
if(r > mid) ins(k<<1|1,l,r,up,id);
P(k);
}
void qry(int k,int l,int r,int up,int id){
if(l <= l(k) && r(k) <= r && val(k) == 1){
if(up(k) >= up) dsu.Merge(id,now(k));
return;
}
D(k);int mid = (l(k) + r(k)) >> 1;
if(l <= mid) qry(k<<1,l,r,up,id);
if(r > mid) qry(k<<1|1,l,r,up,id);
P(k);
}
}T;
struct Matrix{int x1,y1,x2,y2;}a[N];
inline void solve(){
cin>>n;rep(i,1,n,1) cin>>a[i].x1>>a[i].y1>>a[i].x2>>a[i].y2;
sort(a+1,a+1+n,[](Matrix x,Matrix y){return (x.x1==y.x1?x.x2<y.x2:x.x1<y.x1);});
T.B(1,1,1e5);dsu.init(1e5);
rep(i,1,n,1){
T.qry(1,a[i].y1,a[i].y2,a[i].x1,i);
T.ins(1,a[i].y1,a[i].y2,a[i].x2,i);
}
int ans = 0;
rep(i,1,n,1) if(dsu.fa[i] == i) ans++;
cout<<ans;
}
signed main(){
cin.tie(nullptr)->sync_with_stdio(false);
solve();
}
__________________________________________________________________________________________
本文来自博客园,作者:CuFeO4,转载请注明原文链接:https://www.cnblogs.com/hzoi-Cu/p/18523566