【省选模拟】20/05/05 APIO2015_#define

  • 按位贪心有【省选模拟】20/05/05 APIO2015_#define_02【省选模拟】20/05/05 APIO2015_#define_03
    【省选模拟】20/05/05 APIO2015_#ifdef_04【省选模拟】20/05/05 APIO2015_i++_05没有下界,于是令【省选模拟】20/05/05 APIO2015_i++_06表示到【省选模拟】20/05/05 APIO2015_i++_07,合法的最小段数
#include<bits/stdc++.h>
#define cs const
using namespace std;
cs int N = 2e3 + 50;
typedef long long ll;
int n, A, B, a[N]; ll Sum;
namespace FSY{
cs int N = 105;
bool dp[N][N];
bool chk(ll now, int t){
memset(dp,0,sizeof(dp)); dp[0][0]=true;
for(int i=1; i<=n; i++)
for(int j=1; j<=i&&j<=B; j++)
for(ll k=i,x=0; k; k--){
x+=(ll)a[k];
if((x & ((1ll<<t)+now-1)) != x) continue;
dp[i][j]|=dp[k-1][j-1];
} for(int i=A; i<=B; i++) if(dp[n][i]) return true;
return false;
}
void work(){
int k=0; while(Sum) Sum>>=1,++k; ll now=0;
for(int i=k-1;~i;i--) if(!chk(now,i)) now|=1ll<<i;
cout<<now;
}
}
namespace Yolanda{
int dp[N];
bool chk(ll now, int t){
memset(dp,0x3f,sizeof(dp)); dp[0]=0;
for(int i=1; i<=n; i++)
for(ll j=i,x=0; j; j--){
x+=(ll)a[j]; if((x & ((1ll<<t)+now-1)) != x) continue;
dp[i]=min(dp[i],dp[j-1]+1);
} return dp[n]<=B;
}
void work(){
int k=0; while(Sum) Sum>>=1,++k; ll now=0;
for(int i=k-1;~i;i--) if(!chk(now,i)) now|=1ll<<i;
cout<<now;
}
}
int main(){
#ifdef FSYolanda
freopen("1.in","r",stdin);
#endif
scanf("%d%d%d",&n,&A,&B);
for(int i=1; i<=n; i++) scanf("%d",&a[i]), Sum+=(ll)a[i];
if(n<=100) return FSY::work(),0;
else return Yolanda::work(),0;
}

【省选模拟】20/05/05 APIO2015_#ifdef_08

  • 暴力建边是【省选模拟】20/05/05 APIO2015_#define_09,分析一下发现是【省选模拟】20/05/05 APIO2015_i++_10的,即长度【省选模拟】20/05/05 APIO2015_#define_11的边每次最多【省选模拟】20/05/05 APIO2015_#define_12条,本质不同的【省选模拟】20/05/05 APIO2015_i++_13的边最多【省选模拟】20/05/05 APIO2015_#define_14条,每个点可以新转移的边的长度是原本的集合和这步之前到达的长度的集合,集合的总大小和边集大小是一样的,用【省选模拟】20/05/05 APIO2015_i++_15【省选模拟】20/05/05 APIO2015_#define_16判重 可以做到【省选模拟】20/05/05 APIO2015_i++_17
#include<bits/stdc++.h>
#define cs const
#define pb push_back
using namespace std;
typedef pair<int, int> pi;
cs int N = 3e4 + 50;
int n, m, b[N], p[N], mx;
vector<int> G[N]; bitset<N> ok[N];
struct node{ int a, b, d; };
queue<node> q; bool vs[N];
void trans(int v, int dt, int d){
if(!vs[v]){
for(int t : G[v]) if(!ok[v][t])
ok[v][t]=true, q.push({v,t,d}); vs[v]=true;
} if(!ok[v][dt]) ok[v][dt]=true, q.push({v,dt,d});
}
int main(){
#ifdef FSYolanda
freopen("1.in","r",stdin);
#endif
scanf("%d%d",&n,&m); int S=0,T=0;
for(int i=1; i<=m; i++){
scanf("%d%d",&b[i],&p[i]);
if(i==1) S=b[i]; if(i==2) T=b[i];
G[b[i]].pb(p[i]); mx=max(mx,p[i]);
} for(int t : G[S]) q.push({S,t,0}), ok[S][t]=true; vs[S]=true;
while(!q.empty()){
node x = q.front(); q.pop();
int u=x.a, dt=x.b; if(u==T) return cout<<x.d,0;
if(u-dt>=0) trans(u-dt,dt,x.d+1);
if(u+dt<n) trans(u+dt,dt,x.d+1);
} puts("-1"); return 0;
}

【省选模拟】20/05/05 APIO2015_#ifdef_18

  • 按中点排序,存在一个分解点左边的走左边的桥右边的走右边的桥,用数据结构维护中位数即可
#include<bits/stdc++.h>
#define cs const
#define pb push_back
using namespace std;
namespace IO{
cs int Rlen=1<<22|1;
inline char gc(){
static char buf[Rlen],*p1,*p2;
(p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin));
return p1==p2?EOF:*p1++;
}
int read(){
int x=0; char c=gc(); bool f=false;
while(!isdigit(c)) f=c=='-', c=gc();
while(isdigit(c)) x=(((x<<2)+x)<<1)+(c^48), c=gc();
return f?-x:x;
} int op(){
char c=gc(); while(isspace(c)) c=gc();
return c=='A'?0:1;
}
} using namespace IO;
typedef long long ll;
cs ll INF = 1e18;
cs int N = 1e5 + 50;
int K, n, S[N], T[N], bin[N<<1], sz; ll Ans;
namespace zkw{
cs int M = 1<<18;
int sz[M<<1]; ll sm[M<<1];
void clr(){ memset(sz,0,sizeof(sz)); memset(sm,0,sizeof(sm)); }
void add(int x, ll v){ for(x+=M;x;x>>=1) ++sz[x],sm[x]+=v; }
ll query(){
int k=sz[1]>>1, x=1; ll as=0;
while(true){
if(x>M) break; if(k<=sz[x<<1]) x<<=1;
else k-=sz[x<<1], x=x<<1|1;
} int v=bin[x-M]; for(;x;x>>=1){
if(x&1) as+=(ll)sz[x^1]*v-sm[x^1];
else as+=(ll)sm[x^1]-(ll)sz[x^1]*v;
} return as;
}
}
int main(){
#ifdef FSYolanda
freopen("1.in","r",stdin);
#endif
K=read(), n=read(); int m=0;
for(int i=1,x,y; i<=n; i++){
x=op(); S[i]=read(); y=op(); T[i]=read();
if(x==y){ Ans+=(ll)abs(T[i]-S[i]); continue; }
bin[++sz]=S[++m]=S[i], bin[++sz]=T[m]=T[i];
} sort(bin+1,bin+sz+1); n=m;
int x=bin[(sz+1)>>1]; ll mn=0;
for(int i=1; i<=n; i++) mn+=(ll)abs(T[i]-x)+(ll)abs(S[i]-x);
if(K==1) return cout<<Ans+mn+n,0;
sz=unique(bin+1,bin+sz+1)-(bin+1);
static int id[N];
for(int i=1; i<=n; i++) id[i]=i;
sort(id+1,id+n+1,[](cs int &i, cs int &j){
return S[i]+T[i] < S[j]+T[j];
}); static ll pr[N], sf[N];
for(int i=1,x,y,u; i<=n; i++){
u=id[i];
x=lower_bound(bin+1,bin+sz+1,S[u])-bin;
y=lower_bound(bin+1,bin+sz+1,T[u])-bin;
zkw::add(x,S[u]); zkw::add(y,T[u]); pr[i]=zkw::query();
} zkw::clr();
for(int i=n,x,y,u; i>=1; i--){
u=id[i];
x=lower_bound(bin+1,bin+sz+1,S[u])-bin;
y=lower_bound(bin+1,bin+sz+1,T[u])-bin;
zkw::add(x,S[u]); zkw::add(y,T[u]);
sf[i]=zkw::query(); mn=min(mn,pr[i]+sf[i+1]);
} cout<<Ans+mn+n; return 0;
}