noip模拟48
A. Lighthouse
很明显的容斥题,组合式与上上场 \(t2\) 一模一样
注意判环时长度为 \(n\) 的环是合法的
B. Miner
题意实际上是要求偶拉路
对于一个有多个奇数点的联通块,直接 \(dfs\) 是不对的,可能搜索是来的不是一条路径
可以把个数大于 \(2\) 的联通块先强制奇数点两两连边,再跑两个奇数点的偶拉路
直接跑会 \(t\),可以加入类似当前弧优化,注意每次 \(dfs\) 回溯时也要更新边为当前弧
void dfs(int u){
for(int i=hd[u];i;){
hd[u]=edge[i].nxt;
if(!vis[i>>1]){
int v=edge[i].to;
deg[u]--;
deg[v]--;
vis[i>>1]=true;
dfs(v);
sta1[++tp1]=make_pair(edge[i].val,v);
i=hd[u];
}
else i=edge[i].nxt;
}
return ;
}
C. Lyk Love painting
这 \(m\) 幅画居然不能重叠……
首先肯定二分,然后 \(dp\) 验证
设 \(f[i][j]\) 表示第一行选到第 \(i\) 列总共选了 \(j\) 幅画第二行最远选到第几幅画
转移需要双指针预处理第一行,第二行,以及两行从每一列出发最远能到达的距离
D. Revive
先把平方拆开,分为两部分:
- 对于每条边,其平方计算了经过这条边的路径数次,为 \(siz_u(n-siz_u)\)
- 对于每两条边,其乘机的二倍计算了同时经过这两条边的路径次数
可以分三类讨论: - \(v\) 在 \(u\) 子树内,为 \(2(n-siz[u]) * val[u] * siz[v] * val[v]\)
- \(v\) 在 \(u\) 到根节点路径上,为 \(2siz[u] * val[u] * (n-siz[v]) * val[v]\)
- \(v\) 和 \(u\) 的 \(lca\) 不是两点中的任意一个,为 \(2siz[u] * val[u] * siz[v] * val[v]\)
发现和 \(v\) 有关的式子都是 \(siz[v] * val[v]\),那么用线段树维护这个值即可
由于需要维护到根节点路径的值,可以另开一棵记录每个点到根节点的前缀和,这样转化成每次区间修改单点查询,避免了多次跳链的 \(log\)
子树内权值和可以用树状数组维护以卡常
代码实现
#include<bits/stdc++.h>
using namespace std;
#define in long long
#define int long long
const int maxn=1e5+5;
const int maxm=1e5+5;
const int mod=1e9+7;
const int stan=1e15;
in n,m,fa[maxn],x,siz[maxn],re[maxn],dfn[maxn],hd[maxn],cnt,num;
int ans,w,val[maxn],sum[maxn],sum1[maxn],sumtot,c[maxn];
in read(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')f=-1;
ch=getchar();
}
while(isdigit(ch)){
x=x*10+ch-48;
ch=getchar();
}
return x*f;
}
struct Edge{
in nxt,to;
}edge[maxm];
void add(in u,in v){
edge[++cnt].nxt=hd[u];
edge[cnt].to=v;
hd[u]=cnt;
return ;
}
void change1(int x,int w){
for(;x<=n;x+=x&-x)c[x]=(c[x]+w)%mod;
return ;
}
int ask3(int x){
int ans=0;
for(;x;x-=x&-x)ans=(ans+c[x])%mod;
return ans;
}
void modadd(int &x,int y){
x=(x+y)%mod;
if(x<0)x=(x+mod)%mod;
}
void dfs(in u){
siz[u]=1;
for(in i=hd[u];i;i=edge[i].nxt){
in v=edge[i].to;
dfs(v);
siz[u]+=siz[v];
}
return ;
}
void dfs1(in u){
sum[u]=(sum[fa[u]]+siz[u]*val[u]%mod)%mod;
sum1[u]=(sum1[fa[u]]+val[u])%mod;
// cout<<"ppp "<<sum1[u]<<endl;
dfn[u]=++num;
re[num]=u;
for(in i=hd[u];i;i=edge[i].nxt){
in v=edge[i].to;
dfs1(v);
}
return ;
}
struct Seg{
in l,r;
int sum,lazy,sum1,lazy1,sum2,lazy2;
}t[maxn*4];
void update(in p){
t[p].sum=t[p<<1].sum+t[p<<1|1].sum;
t[p].sum1=t[p<<1].sum1+t[p<<1|1].sum1;
// if(t[p].sum>stan)t[p].sum%=mod;
// if(t[p].sum1>stan)t[p].sum1%=mod;
// t[p].sum2=t[p<<1].sum2+t[p<<1|1].sum2;
return ;
}
void build(in p,in l,in r){
t[p].l=l;
t[p].r=r;
if(l==r){
t[p].sum=sum[re[l]];
t[p].sum1=sum1[re[l]];
// t[p].sum2=siz[re[l]]*val[re[l]]%mod;
return ;
}
in mid=l+r>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
update(p);
return ;
}
void tospread(in p,int w1,int w2){
t[p].lazy=t[p].lazy+w1;
t[p].lazy1=t[p].lazy1+w2;
t[p].sum=t[p].sum+w1;
t[p].sum1=t[p].sum1+w2;
return ;
}
//void tospread1(in p,int w){
// t[p].lazy2=t[p].lazy2+w;
// t[p].sum2=t[p].sum2+w;
// return ;
//}
void spread(in p){
tospread(p<<1,t[p].lazy,t[p].lazy1);
tospread(p<<1|1,t[p].lazy,t[p].lazy1);
t[p].lazy=t[p].lazy1=0;
return ;
}
//void spread1(in p){
// tospread1(p<<1,t[p].lazy2);
// tospread1(p<<1|1,t[p].lazy2);
// t[p].lazy2=0;
// return ;
//}
void change(in p,in l,in r,int w1,int w2){
if(l>r)return ;
if(t[p].l>=l&&t[p].r<=r){
tospread(p,w1,w2);
return ;
}
if(t[p].lazy||t[p].lazy1)spread(p);
// if(t[p].lazy2)spread1(p);
in mid=t[p].l+t[p].r>>1;
if(l<=mid)change(p<<1,l,r,w1,w2);
if(r>mid)change(p<<1|1,l,r,w1,w2);
update(p);
return ;
}
//void change1(in p,in l,in r,int w){
// if(l>r)return ;
// if(t[p].l>=l&&t[p].r<=r){
// tospread1(p,w);
// return ;
// }
// if(t[p].lazy||t[p].lazy1)spread(p);
// if(t[p].lazy2)spread1(p);
// in mid=t[p].l+t[p].r>>1;
// if(l<=mid)change1(p<<1,l,r,w);
// if(r>mid)change1(p<<1|1,l,r,w);
// update(p);
// return ;
//}
int ask(in p,in l,in r){
// cout<<t[p].l<<" "<<t[p].r<<" "<<l<<" "<<r<<endl;
if(l>r)return 0;
if(t[p].l>=l&&t[p].r<=r)return t[p].sum;
int mid=t[p].l+t[p].r>>1,ans=0;
if(t[p].lazy||t[p].lazy1)spread(p);
// if(t[p].lazy2)spread1(p);
if(l<=mid)ans=ask(p<<1,l,r);
if(r>mid)ans=ans+ask(p<<1|1,l,r);
if(ans>stan)ans%=mod;
return ans;
}
int ask1(in p,in l,in r){
if(l>r)return 0;
if(t[p].l>=l&&t[p].r<=r)return t[p].sum1;
in mid=t[p].l+t[p].r>>1,ans=0;
if(t[p].lazy||t[p].lazy1)spread(p);
// if(t[p].lazy2)spread1(p);
if(l<=mid)ans=ask1(p<<1,l,r);
if(r>mid)ans=ans+ask1(p<<1|1,l,r);
if(ans>stan)ans%=mod;
return ans;
}
int ask2(in p,in l,in r){
if(l>r)return 0;
if(t[p].l>=l&&t[p].r<=r)return t[p].sum2;
in mid=t[p].l+t[p].r>>1,ans=0;
if(t[p].lazy||t[p].lazy1)spread(p);
// if(t[p].lazy2)spread1(p);
if(l<=mid)ans=ask2(p<<1,l,r);
if(r>mid)ans=ans+ask2(p<<1|1,l,r);
if(ans>stan)ans%=mod;
return ans;
}
int solve(in u,int w,in op){
int res=0;
int sumz=0;
if(siz[u]>1)sumz=ask3(dfn[u]+siz[u]-1)-ask3(dfn[u]);
// int sumz=ask2(1,dfn[u]+1,dfn[u]+siz[u]-1);
// cout<<"hhh "<<u<<" "<<sumz<<endl;
// cout<<ask(1,dfn[u]+1,dfn[u]+siz[u]-1)<<" "<<ask(1,dfn[u],dfn[u])<<endl;
//cout<<"hhh"<<endl;
int suml=ask(1,dfn[fa[u]],dfn[fa[u]])%mod;
// cout<<" "<<ask1(1,dfn[fa[u]],dfn[fa[u]])<<endl;
modadd(res,ask1(1,dfn[fa[u]],dfn[fa[u]])%mod*n%mod-suml);
// cout<<res<<endl;
// cout<<sumtot<<" "<<suml<<" "<<sumz<<endl;
modadd(res,sumtot-suml-siz[u]*val[u]%mod-sumz);
// cout<<res<<endl;
res=2*res*siz[u]%mod*w%mod;
// cout<<res<<endl;
modadd(res,2*w*(n-siz[u])%mod*sumz%mod);
// cout<<"hhh "<<res<<endl;
// cout<<res<<endl;
if(op){
change(1,dfn[u],dfn[u]+siz[u]-1,w*siz[u]%mod,w);
change1(dfn[u],w*siz[u]%mod);
// change1(1,dfn[u],dfn[u],w*siz[u]);
modadd(sumtot,w*siz[u]%mod);
}
return res;
}
int po(int a,int b=mod-2){
int ans=1;
while(b){
if(b&1)ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
signed main(){
// freopen("revive3.in","r",stdin);
// freopen("shuju.in","r",stdin);
// freopen("my.out","w",stdout);
n=read();
n=read(),m=read();
for(int i=2;i<=n;i++){
fa[i]=read();
val[i]=read();
add(fa[i],i);
}
dfs(1);
dfs1(1);
build(1,1,n);
for(int i=1;i<=n;i++)change1(dfn[i],siz[i]*val[i]%mod);
for(int i=1;i<=n;i++)modadd(sumtot,val[i]*siz[i]%mod);
for(int i=2;i<=n;i++){
// cout<<"id: "<<i<<endl;
// cout<<solve(i,val[i],0)<<" ";
ans=(ans+solve(i,val[i],0))%mod;
}
ans=ans*po(2)%mod;
// cout<<ans<<endl;
for(int i=2;i<=n;i++){
ans=(ans+val[i]*val[i]%mod*siz[i]%mod*(n-siz[i])%mod)%mod;
}
cout<<ans<<endl;
for(int i=1;i<=m;i++){
x=read();
w=read();
ans=(ans-val[x]*val[x]%mod*siz[x]%mod*(n-siz[x])%mod)%mod;
ans=(ans+mod)%mod;
ans=(ans+solve(x,w,1))%mod;
val[x]+=w;
val[x]%=mod;
ans=(ans+val[x]*val[x]%mod*siz[x]%mod*(n-siz[x])%mod)%mod;
printf("%lld\n",ans);
}
return 0;
}
noip模拟48的更多相关文章
- CH Round #48 - Streaming #3 (NOIP模拟赛Day1)
A.数三角形 题目:http://www.contesthunter.org/contest/CH%20Round%20%2348%20-%20Streaming%20%233%20(NOIP模拟赛D ...
- NOIP模拟题汇总(加厚版)
\(NOIP\)模拟题汇总(加厚版) T1 string 描述 有一个仅由 '0' 和 '1' 组成的字符串 \(A\),可以对其执行下列两个操作: 删除 \(A\)中的第一个字符: 若 \(A\)中 ...
- 【HHHOJ】NOIP模拟赛 玖 解题报告
点此进入比赛 得分: \(100+20+100=220\)(还不错) 排名: \(Rank\ 16\) \(Rating\):\(+20\) \(T1\):[HHHOJ263]「NOIP模拟赛 玖」三 ...
- 【HHHOJ】NOIP模拟赛 捌 解题报告
点此进入比赛 得分: \(30+30+70=130\)(弱爆了) 排名: \(Rank\ 22\) \(Rating\):\(-31\) \(T1\):[HHHOJ260]「NOIP模拟赛 捌」Dig ...
- NOIP模拟 1
NOIP模拟1,到现在时间已经比较长了.. 那天是6.14,今天7.18了 //然鹅我看着最前边缺失的模拟1,还是终于忍不住把它补上,为了保持顺序2345重新发布了一遍.. # 用 户 名 ...
- NOIP模拟17.9.22
NOIP模拟17.9.22 前进![问题描述]数轴的原点上有一只青蛙.青蛙要跳到数轴上≥
- NOIP 模拟4 T2
本题属于二和一问题 子问题相互对称 考虑对于问题一:知a求b 那么根据b数组定义式 显然能发现问题在于如何求dis(最短路) 有很多算法可供选择 dijsktra,floyed,bfs/dfs,spf ...
- 2021.9.17考试总结[NOIP模拟55]
有的考试表面上自称NOIP模拟,背地里却是绍兴一中NOI模拟 吓得我直接文件打错 T1 Skip 设状态$f_i$为最后一次选$i$在$i$时的最优解.有$f_i=max_{j<i}[f_j+a ...
- NOIP模拟赛20161022
NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...
随机推荐
- OI卷题记录
2021.8.2 LG3386 匈牙利算法 二分图 LG1377 笛卡尔树 题解 2021.8.3 LG2962 \(\text{Meet in middle}\) LG3389 高斯消元 高斯-约旦 ...
- 数据增广imgaug库的使用
记录一下这两天用imgaug库做数据增广的代码,由于是算用算学的,所以只能把代码写出来,具体每种增广算法的原理和一些参数就不得而知了,不过我觉得也没必要把这么些个算法搜搞懂,毕竟重点是扩种数据.所以, ...
- Java 多线程与并发【原理第二部分笔记】
Java 多线程与并发[原理第二部分笔记] 什么是Java内存模型中的happens-before Java内存模型,即JMM,本身是一种抽象的概念,并不是真实存在的,他描述的是一组规则或者说是一种规 ...
- S3C2440—4.时钟系统
文章目录 一.S3C2440时钟体系介绍 1.总线与时钟 2.时钟来源 3.选择时钟 4.产生时钟 5.流程 二.如何配置时钟源 1.设置FCLK频率寄存器 MPLLCON 2.设置分频HDIV.PD ...
- C#/VB.NET 将PDF转为OFD
OFD,全称Open Fixed-layout Document ,是一种可存储.读取以及编辑的国家标准版式的电子文档格式,属于中国的一种自主文件格式,在安全性上有可靠保证.为突破国外技术在我们软硬件 ...
- Android 9.0 默认输入法的设置流程分析
Android 输入法设置文章 Android 9.0 默认输入法的设置流程分析 Android 9.0 添加预置第三方输入法/设置默认输入法(软键盘) 前言 在上一篇文章 Android 9.0 ...
- 为何要打印日志?C++在高并发下如何写日志文件(附源码)?
为何要打印日志?让程序裸奔不是一件很快乐的事么? 有些BUG就像薛定谔的猫,具有波粒二象性,当你试图去观察它时它就消失了,当你不去观察它时,它又会出现.当你在测试人员面前赌咒发誓,亲自路演把程序跑一遍 ...
- 06.SpringBoot核心技术
目录 一.配置文件 二.Web开发 静态资源访问 欢迎页支持 自定义 Favicon 普通参数和基本注解 1.1 @PathVariable 1.2 @RequestHeader 1.3 @Reque ...
- OpenCV 之 自定义滤波
图像处理中,"空间域" 指的是图像平面,因此,空间滤波 可定义为:在图像平面内对像素灰度值进行的滤波 1 空间滤波 1.1 滤波过程 如图,Filter 是一个 3x3 滤波核 ...
- 题解 P3942 将军令
题解 首先看到这题 \(k=1\) 时,就是一道 小胖守皇宫,那么由 \(k=1\) 联想到 \(k=2...20\) 发现可以树形 \(DP\) 但转移方程太难想,不太适合考场做. 考虑贪心: 对所 ...