T1 爆零


贪心地想,肯定要先走完整个子树再走下一个,且要尽量晚地走深度大的叶子。所以对每个点的儿子以子树树高为关键字排序$DFS$即可。

也可$DP$。

$code:$

T1
#include<bits/stdc++.h>
using namespace std; namespace IO{
inline int read(){
char ch=getchar(); int x=0,f=1;
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;
}
inline void write(int x,char sp){
char ch[20]; int len=0;
if(x<0){ putchar('-'); x=~x+1; }
do{ ch[len++]=x%10+(1<<4)+(1<<5); x/=10; }while(x);
for(int i=len-1;~i;--i) putchar(ch[i]); putchar(sp);
}
inline int max(int x,int y){ return x<y?y:x; }
inline int min(int x,int y){ return x<y?x:y; }
inline void swap(int &x,int &y){ x^=y^=x^=y; }
inline void chmax(int &x,int y){ x=x<y?y:x; }
inline void chmin(int &x,int y){ x=x<y?x:y; }
} using namespace IO; const int NN=1e6+5;
int n,pos,ans,mx[NN];
vector<int>to[NN];
bool cmp(int x,int y){ return mx[x]<mx[y]; } namespace tree_chain{
int siz[NN],son[NN],dep[NN],fa[NN],top[NN];
void dfs1(int s,int f){
fa[s]=f; siz[s]=1;
for(auto v:to[s]) if(v!=f){
dep[v]=dep[s]+1;
dfs1(v,s);
siz[s]+=siz[v];
if(siz[son[s]]<siz[v]) son[s]=v;
}
}
void dfs2(int s,int t){
top[s]=t;
if(!son[s]) return;
dfs2(son[s],t);
for(auto v:to[s])
if(v!=fa[s]&&v!=son[s]) dfs2(v,v);
}
inline int LCA(int x,int y){
while(top[x]!=top[y])
if(dep[top[x]]>dep[top[y]]) x=fa[top[x]];
else y=fa[top[y]];
return dep[x]<dep[y]?x:y;
}
} using namespace tree_chain; void dfs3(int s){
mx[s]=dep[s];
for(auto v:to[s]) if(v!=fa[s]){
dfs3(v);
chmax(mx[s],mx[v]);
}
} inline void calc(int p){
ans+=min(dep[pos]+dep[p]-2*dep[LCA(pos,p)],dep[p]);
// cout<<p<<' '<<pos<<' '<<min(dep[pos]+dep[p]-2*dep[LCA(pos,p)],dep[p])<<endl;
pos=p;
}
void dfs(int s){
if(!son[s]) calc(s);
for(auto v:to[s])
if(v!=fa[s]) dfs(v);
} signed main(){
FILE *A=freopen("a.in","r",stdin);
FILE *B=freopen("a.out","w",stdout);
n=read(); pos=1;
for(int a,i=2;i<=n;i++)
a=read(), to[a].push_back(i);
dfs1(1,0); dfs2(1,1); dfs3(1);
for(int i=1;i<=n;i++) sort(to[i].begin(),to[i].end(),cmp);
// for(int i=1;i<=n;i++){cout<<i<<": ";for(auto v:to[i])cout<<v<<",";cout<<endl;}
dfs(1);
write(ans,'\n');
return 0;
}

T2 底垫


用$set$(柯朵莉树)维护区间并记录区间内数字最后出现在哪个“梦境”内,然后对询问按右端点排序,每次将“梦境”扫描到右端点位置,相当于单调指针,一共扫了一遍。

每次加入新区间时会覆盖一些区间,先考虑如果询问只是$[L,R]$区间并的总长应怎么做。可以开一个树装数组,记录当前右端点情况下每个左端点的答案。

在覆盖区间时,如果把长度为$k$,最后出现位置为$t$的区间覆盖掉了,那么就在树状数组中把$[t+1,i]$的答案加上$k$,因为它的出现位置更新后有更多的左端点会被这个区间贡献。

再考虑这道题,首先对一个$[L,R]$区间,选择的方案数是一定的,为$\begin{pmatrix}R-L+2\\ 2\end{pmatrix}$。接下来仍考虑覆盖区间对答案的贡献。

仍设覆盖区间长度为$k$,最后出现位置为$t$,另设覆盖后区间出现位置为$i$,也就是当前梦境位置。

如果最终询问的$L\in [t+1,i]$,那么它对答案的贡献为$(i-L+1)\times(r-i+1)\times k$;否则贡献为$(i-t)\times(r-i+1)\times k$。

于是可以建四个求后缀和的树状数组,分别记$lr,l,r$的系数和常数,在$i$处与$t$处修改即可。

$code:$

T2
#include<bits/stdc++.h>
#define int long long
using namespace std; namespace IO{
inline int read(){
char ch=getchar(); int x=0,f=1;
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;
}
inline void write(int x,char sp){
char ch[20]; int len=0;
if(x<0){ putchar('-'); x=~x+1; }
do{ ch[len++]=x%10+(1<<4)+(1<<5); x/=10; }while(x);
for(int i=len-1;~i;--i) putchar(ch[i]); putchar(sp);
}
inline int max(int x,int y){ return x<y?y:x; }
inline int min(int x,int y){ return x<y?x:y; }
inline void swap(int& x,int& y){ x^=y^=x^=y; }
inline void chmax(int& x,int y){ x=x<y?y:x; }
inline void chmin(int& x,int y){ x=x<y?x:y; }
} using namespace IO; const int NN=2e5+5,p=1e9+7,inv2=5e8+4;
int n,m,tmp,l[NN],r[NN],ans[NN];
struct question{
int l,r,id;
bool operator<(const question& a)const{
return r<a.r;
}
}q[NN];
inline int qpow(int a,int b){
int res=1;
while(b){
if(b&1) res=res*a%p;
a=a*a%p;
b>>=1;
}
return res;
} struct BIT{
int c[NN];
inline void insert(int pos,int x){
while(pos){
(c[pos]+=p+x)%=p;
pos-=pos&-pos;
}
}
inline int query(int pos){
int res=0;
while(pos<=n){
(res+=c[pos])%=p;
pos+=pos&-pos;
}
return res;
}
}ll,rr,lr,cc;
inline void solve(int i,int t,int k){
lr.insert(i,p-k); ll.insert(i,k*(i-1)%p); rr.insert(i,k*(i+1)%p); cc.insert(i,(p+k-k*i%p*i%p)%p);
lr.insert(t,k); ll.insert(t,k*(p+1-i)%p); rr.insert(t,k*(p-i-1)%p); cc.insert(t,(p-k+k*i%p*i%p)%p);
rr.insert(t,k*(i-t)%p); cc.insert(t,k*(p+i+t*i%p-t-i*i%p)%p);
} namespace ODT{
#define sit set<node>::iterator
struct node{
int l,r;
mutable int val;
node(){}
node(int a,int b,int c){ l=a; r=b; val=c; }
node(int a){ l=a; }
bool operator<(const node& a)const{
return l<a.l;
}
};
set<node>s;
inline sit split(int pos){
sit it=s.lower_bound(node(pos));
if(it!=s.end()&&it->l==pos) return it;
--it;
int l=it->l,r=it->r,val=it->val;
s.erase(it); s.insert(node(l,pos-1,val));
return s.insert(node(pos,r,val)).first;
}
inline void assign(int l,int r,int val){
sit itr=split(r+1),itl=split(l);
for(sit it=itl;it!=itr;++it){
int ll=it->l,k=it->r-it->l+1;
solve(val,it->val,k);
}
s.erase(itl,itr);
s.insert(node(l,r,val));
}
} using namespace ODT; signed main(){
FILE *A=freopen("b.in","r",stdin);
FILE *B=freopen("b.out","w",stdout);
n=read(); m=read(); s.insert(node(0,(int)1e9+5,0));
for(int i=1;i<=n;i++) l[i]=read(), r[i]=read()-1;
for(int i=1;i<=m;i++) q[i].l=read(), q[i].r=read(), q[i].id=i;
sort(q+1,q+m+1); tmp=1;
for(int i=1;i<=m;i++){
for(;tmp<=q[i].r;++tmp) assign(l[tmp],r[tmp],tmp);
ans[q[i].id]=q[i].l*q[i].r%p*lr.query(q[i].l)%p+q[i].l*ll.query(q[i].l)%p+q[i].r*rr.query(q[i].l)+cc.query(q[i].l);
ans[q[i].id]%=p;
(ans[q[i].id]*=qpow((q[i].r-q[i].l+1)*(q[i].r-q[i].l+2)%p*inv2%p,p-2))%=p;
}
for(int i=1;i<=m;i++) write(ans[i],'\n');
return 0;
}

T3高考


首先可以发现最后所有局面出现概率相等。

$\frac{\prod(a_i-1)!}{n(n+1)\dots (n+m-1)}\times\frac{m!}{\prod(a_i-1)!}=\frac{1}{\begin{pmatrix}n+m-1\\n-1\end{pmatrix}}$

所以期望题右变成了计数题。考虑设$f_{i,j}$为至少$i$个数字大于等于$j$的方案数,考虑贡献次数,其实对于$r$,答案即为$\sum_{i=1}^r\sum_{j=1}^mf_{i,j}$。

再设$g_{i,j}$为恰有$i$个数字大于等于$j$的方案数,那么$f$即为$g$的后缀和。对于$g$可通过二项式反演求。

$g_{i,j}=\sum_{k=i}^n\begin{pmatrix}k\\ i\end{pmatrix}(-1)^{k-i}\begin{pmatrix}n\\ k\end{pmatrix}\begin{pmatrix}m+n-1-jk\\ n-1\end{pmatrix}$

右边两个组合数可通过划分数的方案来理解。

这样求出的方案默认开始时所有数为$0$,因此每个答案最后要再加$r$。如果要从$1$开始,需要改一改上界和求$g$的式子。

我打的是从$1$开始。

$code:$

T3
#include<bits/stdc++.h>
#define int long long
using namespace std; namespace IO{
inline int read(){
char ch=getchar(); int x=0,f=1;
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;
}
inline void write(int x,char sp){
char ch[20]; int len=0;
if(x<0){ putchar('-'); x=~x+1; }
do{ ch[len++]=x%10+(1<<4)+(1<<5); x/=10; }while(x);
for(int i=len-1;~i;--i) putchar(ch[i]); putchar(sp);
}
inline int max(int x,int y){ return x<y?y:x; }
inline int min(int x,int y){ return x<y?x:y; }
inline void swap(int &x,int &y){ x^=y^=x^=y; }
inline void chmax(int &x,int y){ x=x<y?y:x; }
inline void chmin(int &x,int y){ x=x<y?x:y; }
} using namespace IO; const int NN=5005,p=1e9+7,MX=10010;
int n,m,invv,f[NN][NN],g[NN][NN],fac[MX+1],inv[MX+1];
inline int C(int x,int y){ return x<y?0:fac[x]*inv[y]%p*inv[x-y]%p; }
inline int qpow(int a,int b){
int res=1;
while(b){
if(b&1) res=res*a%p;
a=a*a%p;
b>>=1;
}
return res;
} signed main(){
FILE *A=freopen("c.in","r",stdin);
FILE *B=freopen("c.out","w",stdout);
n=read(); m=read(); fac[0]=inv[0]=1;
for(int i=1;i<=MX;i++) fac[i]=fac[i-1]*i%p; inv[MX]=qpow(fac[MX],p-2);
for(int i=MX-1;i;i--) inv[i]=inv[i+1]*(i+1)%p;
for(int i=1;i<=n;i++)
for(int j=1;j<=m+1&&i*j<=m+n;j++)
for(int k=i;k<=n&&j*k<=m+n;k++){
int tmp=C(n,k)*C(k,i)%p*C(m+n-1-j*k+k,n-1)%p;
(g[i][j]+=(k-i)&1?p-tmp:tmp)%=p;
}
for(int i=n;i;i--) for(int j=1;j<=m+1;j++){
f[i][j]=(f[i+1][j]+g[i][j])%p;
(f[i][0]+=f[i][j])%=p;
}
invv=qpow(C(n+m-1,n-1),p-2);
for(int i=1;i<=n;i++){
(f[i][0]+=f[i-1][0])%=p;
write((f[i][0])*invv%p,'\n');
}
return 0;
}

T4 种田


枚举$\frac{S}{T}$有$70$,精心$rand$有$100$,无正解。

2021.9.18考试总结[NOIP模拟56]的更多相关文章

  1. 2021.10.18考试总结[NOIP模拟76]

    T1 洛希极限 不难发现每个点肯定是被它上一行或上一列的点转移.可以预处理出每个点上一行,上一列最远的能转移到它的点,然后单调队列优化. 预处理稍显ex.可以用并查集维护一个链表,记录当前点之后第一个 ...

  2. 2021.9.17考试总结[NOIP模拟55]

    有的考试表面上自称NOIP模拟,背地里却是绍兴一中NOI模拟 吓得我直接文件打错 T1 Skip 设状态$f_i$为最后一次选$i$在$i$时的最优解.有$f_i=max_{j<i}[f_j+a ...

  3. 2021.9.13考试总结[NOIP模拟52]

    T1 路径 考虑每一位的贡献,第$i$位每$2^i$个数会变一次,那么答案为$\sum_{i=1}^{log_2n} \frac{n}{2^i}$. $code:$ 1 #include<bit ...

  4. 8.18考试总结[NOIP模拟43]

    又挂了$80$ 好气哦,但要保持优雅.(草 T1 地衣体 小小的贪心:每次肯定从深度较小的点向深度较大的点转移更优. 模拟一下,把边按链接点的子树最大深度排序,发现实际上只有上一个遍历到的点是对当前考 ...

  5. 2021.8.11考试总结[NOIP模拟36]

    T1 Dove玩扑克 考场并查集加树状数组加桶期望$65pts$实际$80pts$,考后多开个数组记哪些数出现过,只扫出现过的数就切了.用$set$维护可以把被删没的数去掉,更快. $code:$ 1 ...

  6. 2021.7.29考试总结[NOIP模拟27]

    T1 牛半仙的妹子图 做法挺多的,可以最小生成树或者最短路,复杂度O(cq),c是颜色数. 我考场上想到了原来做过的一道题影子,就用了并查集,把边权排序后一个个插入,记录权值的前缀和,复杂度mlogm ...

  7. 2021.7.15考试总结[NOIP模拟16]

    ZJ模拟D2就是NB.. T1 Star Way To Heaven 谁能想到这竟是个最小生成树呢?(T1挂分100的高人JYF就在我身边 把上边界和下边界看成一个点和星星跑最小生成树,从上边界开始跑 ...

  8. 2021.9.14考试总结[NOIP模拟53]

    T1 ZYB和售货机 容易发现把每个物品都买成$1$是没有影响的. 然后考虑最后一个物品的方案,如果从$f_i$向$i$连边,发现每个点有一个出度多个入度,可以先默认每个物品都能买且最大获利,这样可以 ...

  9. 2021.9.12考试总结[NOIP模拟51]

    T1 茅山道术 仔细观察发现对于每个点只考虑它前面第一个与它颜色相同的点即可. 又仔细观察发现对一段区间染色后以这个区间内点为端点的区间不能染色. 于是对区间右端点而言,区间染色的贡献为遍历到区间左端 ...

随机推荐

  1. Input 只能输入数字,数字和字母等的正则表达式

    JS只能输入数字,数字和字母等的正则表达式 1.文本框只能输入数字代码(小数点也不能输入) <input onkeyup="this.value=this.value.replace( ...

  2. ARM架构安装ubuntu系统

    一.简介 arm开发板制作系统是比较麻烦,不论使用busybox还是yocto制作根文件系统对新手都比太友好,除非深度定制,否则使用ubuntu系统既可以满足,把更多的精力放在应用开发上. 二.准备材 ...

  3. iOS之多语言开发

    前要:iOS多语言开发,可以分为两种 系统设置,通过在手机设置中切换语言,进而改变app中语言: app中手动切换,用户在app中,手动选择语言,进行切换. 一.添加需要的语言 不管使用哪种方法,都需 ...

  4. scrum项目冲刺_day03总结

    摘要:今日完成任务. 1.图像识别已完成,但是较为卡顿,仍需优化 2.语音输入正在进行 3.搜索功能正在进行 总任务: 一.appUI页面(已完成) 二.首页功能: 1.图像识别功能(基本完成) 2. ...

  5. django 常用教程网址

    第一:url中反向解析教程网址 https://docs.djangoproject.com/zh-hans/2.2/ref/templates/builtins/#url

  6. 鸿蒙内核源码分析(信号生产篇) | 信号安装和发送过程是怎样的? | 百篇博客分析OpenHarmony源码 | v48.03

    百篇博客系列篇.本篇为: v48.xx 鸿蒙内核源码分析(信号生产篇) | 年过半百,依然活力十足 | 51.c.h .o 进程管理相关篇为: v02.xx 鸿蒙内核源码分析(进程管理篇) | 谁在管 ...

  7. P6880-[JOI 2020 Final]オリンピックバス【最短路】

    正题 题目链接:https://www.luogu.com.cn/problem/P6880 题目大意 给出\(n\)个点\(m\)条边的有向图,边有边权和一个翻转权值. 翻转至多一条边使得\(1-& ...

  8. Javascript 常见的高阶函数

    高阶函数,英文叫 Higher Order function.一个函数可以接收另外一个函数作为参数,这种函数就叫做高阶函数. 示例: function add(x, y, f) { return f( ...

  9. p3c 插件,是怎么检查出你那屎山的代码?

    作者:小傅哥 博客:https://bugstack.cn 原文:https://mp.weixin.qq.com/s/RwzprbY2AhdgslY8tbVL-A 一.前言 你会对你用到都技术,好奇 ...

  10. FastAPI(62)- FastAPI 部署在 Docker

    Docker 学习 https://www.cnblogs.com/poloyy/p/15257059.html 项目结构 . ├── app │   ├── __init__.py │ └── ma ...