省选模拟45
A. 虚数之树
存下点分树的结构
直接用线段树在上面修改就行
Code
#include<bits/stdc++.h>
#define int long long
#define inf 0x3f3f3f3f
#define meow(args...) fprintf(stderr,args)
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
int n,m,typ,S,rt,lans;
int siz[100010],mx[100010];
bool vis[100010];
vector<int>g[100010];
vector<pair<int,int>>vec[100010];
namespace SEG{
#define lson st[x].ls
#define rson st[x].rs
int rt[100010],tot;
struct seg{int ls,rs,mn;}st[100010*400];
inline void pushup(int x){
st[x].mn=inf;
if(lson) st[x].mn=min(st[x].mn,st[lson].mn);
if(rson) st[x].mn=min(st[x].mn,st[rson].mn);
}
void upd(int &x,int l,int r,int pos,int k){
if(!x) x=++tot;if(l==r) return st[x].mn=k,void();
int mid=(l+r)>>1;
if(pos<=mid) upd(lson,l,mid,pos,k);
else upd(rson,mid+1,r,pos,k);
pushup(x);
}
int query(int x,int l,int r,int L,int R){
if(!x) return inf;if(L<=l&&r<=R) return st[x].mn;
int mid=(l+r)>>1,res=inf;
if(L<=mid) res=min(res,query(lson,l,mid,L,R));
if(R>mid) res=min(res,query(rson,mid+1,r,L,R));
return res;
}
void print(int x,int l,int r){
if(!x) return ;
printf("l : %lld r : %lld mn : %lld\n",l,r,st[x].mn);
if(l==r) return ;
int mid=(l+r)>>1;
print(lson,l,mid);
print(rson,mid+1,r);
}
#undef lson
#undef rson
}
void getrt(int x,int fa){
siz[x]=1,mx[x]=0;
for(auto y:g[x]) if(y!=fa&&!vis[y]){
getrt(y,x);siz[x]+=siz[y];
mx[x]=max(mx[x],siz[y]);
}
mx[x]=max(mx[x],S-siz[x]);
if(mx[x]<mx[rt]) rt=x;
}
void dfs(int x,int fa,int dep){
vec[x].emplace_back(make_pair(rt,dep));
for(auto y:g[x]) if(y!=fa&&!vis[y]) dfs(y,x,dep+1);
}
void solve(int x){
vis[x]=1;dfs(x,0,0);
for(auto y:g[x]) if(!vis[y]){
mx[rt=0]=inf;S=siz[y];getrt(y,0);
mx[rt=0]=inf;S=siz[y];getrt(y,0);
solve(rt);
}
}
inline void ins(int x){for(auto L:vec[x]) SEG::upd(SEG::rt[L.first],1,n,x,L.second);}
inline void del(int x){for(auto L:vec[x]) SEG::upd(SEG::rt[L.first],1,n,x,inf);}
inline int query(int x,int l,int r){
int mn=inf;
for(auto L:vec[x]) mn=min(mn,SEG::query(SEG::rt[L.first],1,n,l,r)+L.second);
return mn;
}
signed main(){
#ifdef LOCAL
freopen("in","r",stdin);
freopen("out","w",stdout);
#endif
freopen("regression.in","r",stdin);
freopen("regression.out","w",stdout);
n=read();m=read();read();typ=read();
for(int i=1,x,y;i<n;i++){
x=read(),y=read();
g[x].emplace_back(y);
g[y].emplace_back(x);
}
S=n,mx[rt=0]=inf;getrt(1,0);solve(rt);
for(int i=1,opt,x,l,r,v;i<=m;i++){
opt=read();
if(opt==1){x=read()^(lans*typ);ins(x);}
if(opt==2){x=read()^(lans*typ);del(x);}
if(opt==3){
l=read();r=read();x=read()^(lans*typ);
v=query(x,l,r);
if(v<=n) printf("%lld\n",lans=v);else printf("-1\n");
}
}
return 0;
}
B. 速通
前几天原题,注意转移细节
Code
#include<bits/stdc++.h>
#define int long long
#define rint signed
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
int n,lim;
int fa[110],L[110],R[110];
double f[110][1010],p[110],ans=1e10,sum,T;
vector<int>g[110];
void dfs(int x){
for(auto y:g[x]) dfs(y);
for(int i=0;i<=lim;i++){
double div=1.0/(R[x]-L[x]+1),tmp=0;
for(int j=L[x];j<=R[x];j++){
if(i+j>lim){f[x][i]+=(T+j);continue;}
if(g[x].empty()){f[x][i]+=j;continue;}
sum=0;for(auto y:g[x]) sum+=f[y][i+j]*p[y];
tmp=sum+j;tmp=min(tmp,(double)T+j);
f[x][i]+=tmp;
}
f[x][i]*=div;
}
}
inline bool check(double mid){
memset(f,0,sizeof(f));
T=mid;dfs(1);
return f[1][0]<=mid;
}
signed main(){
#ifdef LOCAL
freopen("in","r",stdin);
freopen("out","w",stdout);
#endif
freopen("isaac.in","r",stdin);
freopen("isaac.out","w",stdout);
ios::sync_with_stdio(false);cin.tie(0);
cin>>n>>lim;
for(int i=1;i<=n;i++) cin>>L[i]>>R[i];
for(int i=2;i<=n;i++){
cin>>fa[i]>>p[i];
g[fa[i]].emplace_back(i);
}
double l=0,r=1000000000;
while(r-l>1e-8){
double mid=(l+r)/2.0;
if(check(mid)) r=mid,ans=mid;
else l=mid;
}
if(ans>1e9) puts("Remake");else printf("%.8lf\n",ans);
return 0;
}
C. 叮叮车
发现 \(f(i)\) 其实就是卡特兰数
再乘上一个 \((i+1)\) 就变成了 \(\frac{2n!}{n!\times n!}\)
根据库默尔定理,答案就是在 \(7\) 进制下进位的次数
于是每一位的数越大越好
贴着上界走,将这一位减 \(1\) 再把后边都填成 \(6\)
也可以数位 \(dp\)
Code
#include<bits/stdc++.h>
#define int long long
#define inf 0x3f3f3f3f3f3f3f3f
#define meow(args...) fprintf(stderr,args)
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
int ll,rr,L,ans,v;
int a[100010],b[100010];
int A[100010],B[100010],C[100010];
char l[100010],r[100010];
inline int calc(){
int res=0;
for(int i=1;i<=rr;i++) C[i]*=2;
for(int i=1;i<=rr;i++) if(C[i]>=7){
res+=C[i]/7;C[i+1]+=C[i]/7;C[i]%=7;
if(i==rr) rr++;
}
return res;
}
signed main(){
#ifdef LOCAL
freopen("in","r",stdin);
freopen("out","w",stdout);
#endif
freopen("dingdingcar.in","r",stdin);
freopen("dingdingcar.out","w",stdout);
scanf("%s",l+1);ll=strlen(l+1);reverse(l+1,l+1+ll);
scanf("%s",r+1);rr=strlen(r+1);reverse(r+1,r+1+rr);
for(int i=1;i<=ll;i++) a[i]=l[i]-'0';a[0]=1;
for(int i=1;i<=rr;i++) b[i]=r[i]-'0';b[0]=1;
for(int i=1,now=0;ll;i++){
for(int j=ll;j;j--){
now=now*10+a[j];a[j]=now/7;now%=7;
if(j==ll&&a[j]==0) ll--;
}
A[++A[0]]=now;now=0;
}
for(int i=1,now=0;rr;i++){
for(int j=rr;j;j--){
now=now*10+b[j];b[j]=now/7;now%=7;
if(j==rr&&b[j]==0) rr--;
}
B[++B[0]]=now;now=0;
}
rr=B[0];
for(int i=rr;i;i--) if(B[i]!=A[i]){L=i;break;}
for(int K=L;~K;K--){
memset(C,0,sizeof(C));
for(int i=rr;i>K;i--) C[i]=B[i];C[K]=B[K]-1;for(int i=K-1;i>0;i--) C[i]=6;
ans=max(ans,calc());
}
printf("%lld\n",ans);
return 0;
}