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();
}

image

排列

笛卡尔树上dp,不会……
image

最短路

写了个搜索+剪枝,过了大样例,能拿50比较牛。然而事实是只加一个最优性剪枝就过了,时间复杂度\(O(能过OJ的水数据)\),当然,这是错的。挂个好不容易才卡出来的。

image

点此查看代码
#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();    
}

posted @ 2024-11-04 16:51  CuFeO4  阅读(27)  评论(0)    收藏  举报