noip模拟56 solutions
忘了啥感觉了,好像考得不咋地。。。。
T1 爆零
原题直接dp,然后我是\(\mathcal{O(nlogn)}\)的
AC_code
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int n,fa[N];
int to[N*2],nxt[N*2],head[N],rp;
void add_edg(int x,int y){
to[++rp]=y;
nxt[rp]=head[x];
head[x]=rp;
}
int dep[N],mxd[N];
void dfs_pre(int x,int d){
dep[x]=d;mxd[x]=dep[x];
for(int i=head[x],y;i;i=nxt[i]){
y=to[i];dfs_pre(y,d+1);
mxd[x]=max(mxd[x],mxd[y]);
}
}
struct node{
int who,mxn;
node(){}
node(int x,int y){who=x;mxn=y;}
bool operator < (node a)const{return mxn<a.mxn;}
};
vector<node> vec[N];
int sum[N],ans[N];
void dfs_ans(int x){
if(!head[x]){sum[x]=1;return ;}
for(int i=head[x],y;i;i=nxt[i]){
y=to[i];dfs_ans(y);
vec[x].push_back(node(y,mxd[y]));
ans[x]+=sum[y];
}
sort(vec[x].begin(),vec[x].end());
fo(i,0,vec[x].size()-1){
if(i&&vec[x][i-1].mxn-dep[x]<dep[x])sum[x]--,ans[x]+=vec[x][i-1].mxn-dep[x];
sum[x]+=sum[vec[x][i].who];ans[x]+=ans[vec[x][i].who];
}
}
signed main(){
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
scanf("%d",&n);
fo(i,2,n)scanf("%d",&fa[i]),add_edg(fa[i],i);
dfs_pre(1,1);dfs_ans(1);
printf("%d",ans[1]);
}
T2 底垫
考场上只会\(\mathcal{O(n^2logn)}\)的做法
所以我只拿了45pts,不对,我数组开小了所以拿了20pts
正解是珂朵莉树,用set拆分区间,然后用后缀的树状数组维护
因为你维护的是对于每一个右端点来说的左端点,从后往前走
主要是找好式子,就按照官方上的那个式子拆开就好了
AC_code
#include<bits/stdc++.h>
using namespace std;
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
#define int long long
const int N=2e5+5;
const int mod=1e9+7;
int n,m,ans[N];
struct QUS{
int l,r,id;QUS(){}
bool operator < (QUS x)const{return r<x.r;}
}qus[N];
struct dream{
int l,r,t;dream(){}
}sca[N];
struct BIT{
int sum[N];
BIT(){}
void ins(int x,int v){for(int i=x;i;i-=i&(-i))(sum[i]+=v)%=mod;}
int get(int x){int ret=0;for(int i=x;i<=n;i+=i&(-i))(ret+=sum[i])%=mod;return ret;}
}ql,qr,qlr,qc;
struct kdl{
int l,r,t;kdl(){}
kdl(int x,int y,int z){l=x;r=y;t=z;}
bool operator < (kdl x)const{return l<x.l;}
};
set<kdl> st;
set<kdl>::iterator spilt(int x){
set<kdl>::iterator it=st.lower_bound(kdl(x,0,-1));
if(it->l==x)return it;
it=prev(it);int l=it->l,r=it->r,t=it->t;
st.erase(it);st.insert(kdl(l,x-1,t));
return st.insert(kdl(x,r,t)).first;
}
int ksm(int x,int y){
int ret=1;
while(y){
if(y&1)ret=ret*x%mod;
x=x*x%mod;y>>=1;
}return ret;
}
void sol(int x){
set<kdl>::iterator beh=spilt(sca[x].r+1);
set<kdl>::iterator fro=spilt(sca[x].l);
while(fro!=beh){
int k=fro->r-fro->l+1,ft=fro->t,jus;
ql.ins(sca[x].t,jus=k*(sca[x].t-1)%mod);
ql.ins(ft,(mod-jus)%mod);
qr.ins(sca[x].t,jus=k*(sca[x].t+1)%mod);
qr.ins(ft,(mod-jus)%mod);
qr.ins(ft,k*(sca[x].t+mod-ft)%mod);
qlr.ins(sca[x].t,jus=(mod-k)%mod);
qlr.ins(ft,(mod-jus)%mod);
qc.ins(sca[x].t,jus=k*(mod+1-sca[x].t*sca[x].t%mod)%mod);
qc.ins(ft,(mod-jus)%mod);
qc.ins(ft,k*(sca[x].t*ft%mod+mod-ft%mod-sca[x].t*sca[x].t%mod+mod+sca[x].t)%mod);
fro=next(fro);st.erase(prev(fro));
}
st.insert(kdl(sca[x].l,sca[x].r,sca[x].t));
return ;
}
signed main(){
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
scanf("%lld%lld",&n,&m);
fo(i,1,n)scanf("%lld%lld",&sca[i].l,&sca[i].r),sca[i].t=i,sca[i].r--;
fo(i,1,m)scanf("%lld%lld",&qus[i].l,&qus[i].r),qus[i].id=i;
sort(qus+1,qus+m+1);int it=0;
st.insert(kdl(0,1e9,0));
fo(i,1,m){
int fz=0,fm=(qus[i].r-qus[i].l+1)*(qus[i].r-qus[i].l+2)/2%mod;
while(it<qus[i].r)it++,sol(it);
fz=(fz+qus[i].l*ql.get(qus[i].l))%mod;
fz=(fz+qus[i].r*qr.get(qus[i].l))%mod;
fz=(fz+qus[i].l*qus[i].r%mod*qlr.get(qus[i].l))%mod;
fz=(fz+qc.get(qus[i].l))%mod;
ans[qus[i].id]=fz*ksm(fm,mod-2)%mod;
}
fo(i,1,n)printf("%lld\n",ans[i]);
}
T3 高考
首先证明所有情况是等概率的,注意这里指的是不排序的情况
然后直接递归回去
AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
const int N=5005;
const int mod=1e9+7;
int n,m;
int jc[N*2],inv[N*2],nc[N*2];
int g[N][N],f[N][N],ans[N];
int ksm(int x,int y){
int ret=1;
while(y){
if(y&1)ret=ret*x%mod;
x=x*x%mod;y>>=1;
}
return ret;
}
int C(int x,int y){return jc[x]*inv[y]%mod*inv[x-y]%mod;}
signed main(){
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
scanf("%lld%lld",&n,&m);
jc[0]=1;fo(i,1,n+m)jc[i]=jc[i-1]*i%mod;
inv[0]=1;inv[n+m]=ksm(jc[n+m],mod-2);
fu(i,n+m-1,1)inv[i]=inv[i+1]*(i+1)%mod;
nc[0]=1;fo(i,1,n+m)nc[i]=nc[i-1]*n%mod;
fo(i,1,n)fo(j,1,m/i){
int bas=1;
fo(k,i,m/j)g[i][j]=(g[i][j]+bas*C(k,i)*C(n,k)%mod*C(m+n-1-j*k,n-1)%mod+mod)%mod,bas=-bas;
}
fo(j,1,m)fu(i,m/j,1)f[i][j]=(f[i+1][j]+g[i][j])%mod;
fo(i,1,n){
fo(j,1,m/i)ans[i]=(ans[i]+f[i][j])%mod;
ans[i]=(ans[i]+ans[i-1])%mod;
printf("%lld\n",(ans[i]*ksm(C(n+m-1,n-1),mod-2)+i)%mod);
}
}