多校A层冲刺NOIP2024模拟赛09

又双叒叕垫底啦

rank 4,T1 50,T2 100,T3 39,T4 35。

accoder 上同分,rank 20

排列最小生成树 (pmst)

打的O(n2logn2)暴力

发现总是存在⼀颗⽣成树,使得⽣成树⾥的所有边的边权都⼩于n
考虑 Kruskal 的过程,我们只需要留下那些边权⼩于n的边。

然后用桶排序即可。

点此查看代码
#include<bits/stdc++.h>
#include<bits/extc++.h>
// using namespace __gnu_pbds;
// using namespace __gnu_cxx;
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)
#define Infile(x) freopen(#x".in","r",stdin)
#define Outfile(x) freopen(#x".out","w",stdout)
#define Ansfile(x) freopen(#x".ans","w",stdout)
#define Errfile(x) freopen(#x".err","w",stderr)
#ifdef LOCAL
FILE *InFile = Infile(in),*OutFile = Outfile(out);
// FILE *ErrFile = Errfile(err);
#else
FILE *InFile = Infile(pmst),*OutFile = Outfile(pmst);
#endif
using ll=long long;using ull=unsigned long long;
using db = double;using ldb = long double;
const int N = 5e4 + 10;
#define pii pair<int,int>
#define mk make_pair
int n,len,fa[N];
vector<pii> ct[N];
inline int get_fa(int x){while(x != fa[x]) x = fa[x] = fa[fa[x]];return x;}
int cx[N],cy[N];
inline void solve(){
cin>>n;
rep(i,1,n,1){int x;cin>>x;cx[i] = x;cy[x] = i;}
len = sqrt(n);
rep(i,1,n,1){
rep(j,i+1,min(i+len,n),1){
int val;
val = abs(cx[i]-cx[j])*(j-i);
if(val <= n) ct[val].emplace_back(mk(i,j));
val = abs(cy[i]-cy[j])*(j-i);
if(val <= n) ct[val].emplace_back(mk(cy[i],cy[j]));
}
}
int tot = 0;
rep(i,1,n,1) fa[i] = i;
ll ans = 0;
rep(i,1,n,1) for(auto j:ct[i]){
int x = j.first,y = j.second;
x = get_fa(x),y = get_fa(y);
if(x == y) continue;
fa[x] = y,ans += i,tot++;
if(tot == n-1) break;
}
cout<<ans<<'\n';
}
signed main(){
cin.tie(nullptr)->sync_with_stdio(false);
solve();
}

卡牌游戏 (cardgame)

签。

发现循环节是lcm,然后找规律即可。大体的规律就是i[1,gcd(n,m)]所有的k1i=0,k2i=0(1k1n,1k2m)都会组一次队。

然后对于每一个i处理,离散化后开个权值树状数组维护即可。时间复杂度O(nlogn)

注意不能用memset清空

点此查看代码
#include<bits/stdc++.h>
#include<bits/extc++.h>
// using namespace __gnu_pbds;
// using namespace __gnu_cxx;
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)
#define Infile(x) freopen(#x".in","r",stdin)
#define Outfile(x) freopen(#x".out","w",stdout)
#define Ansfile(x) freopen(#x".ans","w",stdout)
#define Errfile(x) freopen(#x".err","w",stderr)
#ifdef LOCAL
FILE *InFile = Infile(in),*OutFile = Outfile(out);
// FILE *ErrFile = Errfile(err);
#else
FILE *InFile = Infile(cardgame),*OutFile = Outfile(cardgame);
#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,m,a[N],b[N],ans1,ans2,ans3;
#define eb emplace_back
struct BIT{
int tree[N<<1],mx;
inline int lowbit(int x){return (x&(-x));}
inline void upd(int pos,int val){rep(i,pos,mx,lowbit(i)) tree[i] += val;}
inline int qry(int pos){int res = 0;drep(i,pos,1,lowbit(i)) res += tree[i];return res;}
}T;
inline void get_ans(int &ans1,int &ans2,int &ans3){
int gcd = __gcd(n,m);
rep(i,1,gcd,1){
int res = 0;
rep(j,i,n,gcd) T.upd(a[j],1),res++;
rep(j,i,m,gcd){
ans2 += T.qry(b[j]-1);
ans3 += T.qry(b[j]) - T.qry(b[j]-1);
ans1 += res - T.qry(b[j]);
}
rep(j,i,n,gcd) T.upd(a[j],-1);
}
ans1 *= gcd;ans2 *= gcd;ans3 *= gcd;
}
inline void solve(){
cin>>n>>m;
rep(i,1,n,1) cin>>a[i];
rep(i,1,m,1) cin>>b[i];
vector<int> num;
rep(i,1,n,1) num.eb(a[i]);rep(i,1,m,1) num.eb(b[i]);
sort(num.begin(),num.end());
num.erase(unique(num.begin(),num.end()),num.end());
T.mx = num.size();
rep(i,1,n,1) a[i] = lower_bound(num.begin(),num.end(),a[i]) - num.begin() + 1;
rep(i,1,m,1) b[i] = lower_bound(num.begin(),num.end(),b[i]) - num.begin() + 1;
if(n > m) swap(n,m),swap(a,b),get_ans(ans2,ans1,ans3);
else get_ans(ans1,ans2,ans3);
cout<<ans1<<'\n'<<ans2<<'\n'<<ans3<<'\n';
}
signed main(){
cin.tie(nullptr)->sync_with_stdio(false);
solve();
}

比特跳跃 (jump)

诡异建图题,没调出来,打的暴力与特殊性质。

S=1时,发现只有n=(2k)1时,到第n个点的最短路才有权值。

S=2时,发现只需要考虑改变一位即可。

s=3时,发现x|ymax(x,y),所以如果跳跃到i的如果不是从j(j|i=i)过来的,那么一定不如从1跳过来。然后只需要考虑改变一位即可,用上拓展域跑一遍即可。

点此查看代码
#include<bits/stdc++.h>
#include<bits/extc++.h>
// using namespace __gnu_pbds;
// using namespace __gnu_cxx;
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)
#define Infile(x) freopen(#x".in","r",stdin)
#define Outfile(x) freopen(#x".out","w",stdout)
#define Ansfile(x) freopen(#x".ans","w",stdout)
#define Errfile(x) freopen(#x".err","w",stderr)
#ifdef LOCAL
FILE *InFile = Infile(in),*OutFile = Outfile(out);
// FILE *ErrFile = Errfile(err);
#else
FILE *InFile = Infile(jump),*OutFile = Outfile(jump);
#endif
using ll=long long;using ull=unsigned long long;
using db = double;using ldb = long double;
const int N = 2e6 + 10;
struct Edge{
struct EDGE{int to,next;ll w;}edge[N<<1];
int head[N],cnt;
inline void Add(int u,int v,ll w){
// cerr<<u<<' '<<v<<' '<<w<<'\n';
edge[++cnt] = {v,head[u],w};head[u] = cnt;
edge[++cnt] = {u,head[v],w};head[v] = cnt;
}
inline void add(int u,int v,ll w){
edge[++cnt] = {v,head[u],w};head[u] = cnt;
}
#define repe(i,x,y,e) for(int i = e.head[x],y = e.edge[i].to; i;i = e.edge[i].next)
}g;
ll dist[N];
bitset<N> vis;
int n,m,s,k;
#define pii pair<ll,int>
#define mk make_pair
inline void dijkstra(int s){
priority_queue<pii,vector<pii>,greater<pii> > q;
memset(dist,0x3f,sizeof dist);
dist[s] = 0;q.push(mk(dist[s],s));
// cout<<'\n';
while(q.size()){
int x = q.top().second;q.pop();
// cerr<<x<<'\n';
if(vis[x]) continue;
vis[x] = true;
for(int i = g.head[x]; i;i = g.edge[i].next){
int y = g.edge[i].to;
if(dist[y] > dist[x] + g.edge[i].w){
dist[y] = dist[x] + g.edge[i].w;
q.push(mk(dist[y],y));
}
}
}
}
int sta[N],id[N];
inline void solve(){
cin>>n>>m>>s>>k;
int lg = log2(n);
rep(i,1,m,1){
int u,v,w;cin>>u>>v>>w;
g.Add(u,v,w);
}
if(s == 1){
g.Add(1,n+1,0);
rep(i,2,n,1) rep(j,0,lg,1)
if(!(i&(1<<j))) g.Add(i,n+1,0);
}
if(s == 2){
rep(i,0,n,1) rep(j,0,lg,1){
if((i^(1<<j))&&(i^(1<<j)) <= n)
g.Add(i,i^(1<<j),1ll*k*(1<<j));
}
}
if(s == 3){
rep(i,1,n,1) sta[i] = i+1;
int tt = n;
sort(sta+1,sta+1+n,[](int x,int y){return __builtin_popcount(x) < __builtin_popcount(y);});
rep(i,1,n,1) g.Add(1,i,1ll*k*(i|1));
rep(i,1,n,1){
int s = sta[i];
id[s] = ++tt;
g.add(s,id[s],0);g.add(id[s],s,1ll*s*k);
rep(j,0,lg,1) if(s&(1<<j)) g.add(id[s^(1<<j)],id[s],0);
}
}
dijkstra(1);
rep(i,2,n,1) cout<<dist[i]<<' ';
}
signed main(){
cin.tie(nullptr)->sync_with_stdio(false);
solve();
}

区间 (interval)

打的O(n2+q)的。滚去学DS的,等学到再打。

posted @   CuFeO4  阅读(42)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示