多校A层冲刺NOIP2024模拟赛06
rank 19,T1 100pts,T2 30pts,T3 45pts,T4 20pts
T1 小Z的手套(gloves)
二分答案,贪心匹配\(O(n\log n)\)的check即可。
时间复杂度\(O(n\log^2 n)\)
点此查看代码
#include<bits/stdc++.h>
#include<bits/extc++.h>
// using namespace __gnu_pbds;
// using namespace __gnu_cxx;
using namespace std;
#define infile(x) freopen(x,"r",stdin)
#define outfile(x) freopen(x,"w",stdout)
#define errfile(x) freopen(x,"w",stderr)
#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 = infile("in.in"),*OutFile = outfile("out.out");
// FILE *ErrFile=errfile("err.err");
#else
FILE *Infile = infile("gloves.in"),*OutFile = outfile("gloves.out");
//FILE *ErrFile = stderr;
#endif
using ll=long long;using ull=unsigned long long;
using db = double;using ldb = long double;
const int N = 1e5 + 10;
int n,m,a[N],b[N];
inline bool check(int mid){
bitset<N> vis;vis.set();
rep(i,1,n,1){
int pos = upper_bound(b+1,b+1+m,a[i] - mid - 1) - b - 1;
int p = vis._Find_next(pos);
if(abs(b[p] - a[i]) > mid || p > m) return false;
vis[p] = false;
}
return true;
}
inline void solve(){
cin>>n>>m;
rep(i,1,n,1) cin>>a[i];rep(i,1,m,1) cin>>b[i];
sort(a+1,a+1+n);sort(b+1,b+1+m);
if(n > m) swap(n,m),swap(a,b);
int l = 0,r = 1e9,ans = 0;
while(l <= r){
int mid = (l + r) >> 1;
if(check(mid)) ans = mid,r = mid - 1;
else l = mid + 1;
}
cout<<ans<<'\n';
}
signed main(){
cin.tie(nullptr)->sync_with_stdio(false);
cout.tie(nullptr)->sync_with_stdio(false);
solve();
}
小 Z 的字符串(string)
动态规划。
记\(f_{i,j,k,l}\)表示在前\(i\)个位置上,0放了\(j\)个,1放了\(k\)个,第\(i\)位上为\(l\in\{0,1,2\}\)的最小花费。
最后的答案为\(\frac{\min\limits_{i=0}^2 f_{n,ct_0,ct_1,i}}{2}\)
至于为什么除以二,因为一个去一个回,都算过了一遍。
点此查看代码
#include<bits/stdc++.h>
#include<bits/extc++.h>
// using namespace __gnu_pbds;
// using namespace __gnu_cxx;
using namespace std;
#define infile(x) freopen(x,"r",stdin)
#define outfile(x) freopen(x,"w",stdout)
#define errfile(x) freopen(x,"w",stderr)
#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 = infile("in.in"),*OutFile = outfile("out.out");
// FILE *ErrFile=errfile("err.err");
#else
FILE *Infile = infile("string.in"),*OutFile = outfile("string.out");
//FILE *ErrFile = stderr;
#endif
using ll=long long;using ull=unsigned long long;
using db = double;using ldb = long double;
const int N = 410;
int f[N/2][N/2][N/2][3],t[3][N],n,ct[3];
char s[N];
inline void solve(){
cin>>(s+1);n = strlen(s+1);
rep(i,1,n,1) t[s[i]-'0'][++ct[s[i]-'0']] = i;
if(max({ct[0],ct[1],ct[2]}) > (n+1)/2) cout<<"-1\n",exit(0);
memset(f,0x3f,sizeof f);
f[0][0][0][0] = f[0][0][0][1] = f[0][0][0][2] = 0;
rep(i,0,ct[0],1) rep(j,0,ct[1],1) rep(k,0,ct[2],1){
int p = i + j + k;
if(i) f[i][j][k][0] = min(f[i-1][j][k][1],f[i-1][j][k][2]) + abs(p - t[0][i]);
if(j) f[i][j][k][1] = min(f[i][j-1][k][0],f[i][j-1][k][2]) + abs(p - t[1][j]);
if(k) f[i][j][k][2] = min(f[i][j][k-1][0],f[i][j][k-1][1]) + abs(p - t[2][k]);
}
cout<<min({f[ct[0]][ct[1]][ct[2]][0],f[ct[0]][ct[1]][ct[2]][1],f[ct[0]][ct[1]][ct[2]][2]})/2;
}
signed main(){
cin.tie(nullptr)->sync_with_stdio(false);
cout.tie(nullptr)->sync_with_stdio(false);
solve();
}
一个真实的故事(truth)
线段树+双指针。记录一下每个值在每一段最左侧的位置和最右侧的位置,然后pushup的时候将左右儿子的归并起来,跑遍\(O(k)\)的双指针即可。
时间复杂度\(O(nk\log n +qk\log n)\)
点此查看代码
#include<bits/stdc++.h>
#include<bits/extc++.h>
// using namespace __gnu_pbds;
// using namespace __gnu_cxx;
using namespace std;
#define infile(x) freopen(x,"r",stdin)
#define outfile(x) freopen(x,"w",stdout)
#define errfile(x) freopen(x,"w",stderr)
#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 = infile("in.in"),*OutFile = outfile("out.out");
// FILE *ErrFile=errfile("err.err");
#else
FILE *Infile = stdin,*OutFile = stdout;
//FILE *ErrFile = stderr;
#endif
using ll=long long;using ull=unsigned long long;
using db = double;using ldb = long double;
namespace IO{
char buf[1<<23],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread_unlocked(buf,1,1<<23,stdin),p1==p2)?EOF:*p1++)
#define pc putchar_unlocked
template<class T>
inline void read(T &x){
x = 0;
char s = gc();
for(;s < '0' || s > '9';s = gc());
for(;'0' <= s && s <= '9';s = gc()) x = (x<<1)+(x<<3)+(s^48);
}
template<class T,class... Args>
inline void read(T &x,Args&... argc){read(x);read(argc...);}
template<class T>
inline void write(T x){
static int sta[20],top = 0;
do{sta[++top] = x%10,x /= 10;}while(x);
do{pc(sta[top--]+'0');}while(top);
}
inline void write(char x){pc(x);}
template<class T,class... Args>
inline void write(T x,Args... argc){write(x);write(argc...);}
}using namespace IO;
const int N = 1e5+ 10,inf = 0x3f3f3f3f;
int n,m,a[N],K;
struct Segment_Tree{
struct segment_tree{
int l,r,ans;
bitset<51> h;
int pl[51],pr[51];
#define pl(k) tree[k].pl
#define pr(k) tree[k].pr
#define l(k) tree[k].l
#define r(k) tree[k].r
#define h(k) tree[k].h
#define ans(k) tree[k].ans
}tree[N<<2];
inline void pushup(int k){
int ls = k<<1,rs = k<<1|1;
h(k) = h(ls)|h(rs);
rep(i,1,K,1)
pl(k)[i] = min({pl(ls)[i],pl(rs)[i]}),
pr(k)[i] = max({pr(rs)[i],pr(ls)[i]});
if(h(k).count() != K) return ans(k) = inf,void();
vector<int> pos;pos.emplace_back(0);
rep(i,1,K,1){
if(1 <= pr(ls)[i] && pr(ls)[i] <= n) pos.emplace_back(pr(ls)[i]);
if(1 <= pl(rs)[i] && pl(rs)[i] <= n) pos.emplace_back(pl(rs)[i]);
}
sort(pos.begin(),pos.end());
int ln = pos.size() - 1;
int ct[51] = {0},res = 0;
ans(k) = inf;
for(int l = 1,r = 1;l <= ln; ++l){
while(res < K && r <= ln){
if(!ct[a[pos[r]]]) res++;
ct[a[pos[r]]]++;
r++;
}
if(res == K) ans(k) = min(ans(k),pos[r-1]-pos[l]+1);
ct[a[pos[l]]]--;
if(!ct[a[pos[l]]]) res--;
}
ans(k) = min({ans(k),ans(ls),ans(rs)});
}
void build(int k,int l,int r){
l(k) = l,r(k) = r;
rep(i,1,K,1) pl(k)[i] = inf,pr(k)[i] = -inf;
if(l == r){
h(k).set(a[l]),pl(k)[a[l]] = pr(k)[a[l]] = l,
ans(k) = h(k).count()==K?1:inf;
return void();
}
int mid = (l + r) >> 1;
build(k<<1,l,mid);build(k<<1|1,mid+1,r);
pushup(k);
}
void update(int k,int pos,int val){
if(l(k) == r(k)){
h(k).reset(a[pos]);
pl(k)[a[pos]] = inf;
pr(k)[a[pos]] = -inf;
pl(k)[val] = pr(k)[val] = pos;
h(k).set(val);a[pos] = val;
ans(k) = h(k).count()==K?1:inf;
return;
}
int mid = (l(k) + r(k)) >> 1;
if(pos <= mid) update(k<<1,pos,val);
else update(k<<1|1,pos,val);
pushup(k);
}
}T;
inline void solve(){
read(n,K,m);
rep(i,1,n,1) read(a[i]);
T.build(1,1,n);
while(m--){
int op;read(op);
if(op ^ 1){
if(T.ans(1) == inf) puts("-1");
else write(T.ans(1),'\n');}
else{
int pos,val;read(pos,val);T.update(1,pos,val);
}
}
}
signed main(){
solve();
}
异或区间(xor)
不会
__________________________________________________________________________________________
本文来自博客园,作者:CuFeO4,转载请注明原文链接:https://www.cnblogs.com/hzoi-Cu/p/18461278