NOIP模拟67
前言
从这一次到 71 都是多校联考了,尽管考的不咋样。。
T1 数据恢复
解题思路
这个题真的是。。
先声明一个点,对于优先队列以及 set 都是在某个元素插入的时候进行比较,但是在之后如果修改比较条件的话也不会改变它的位置。。(好像只有我不知道)
对于上述情况我们可以用 set 删掉再加入一遍,或者建立一个合并后的假点。。
对于这个题而言对于一个点如果它的依赖已经可行直接计入贡献,否则就把它所在联通快和它父亲的联通快相连新的 \(a,b\) 值就是两个的和,同时还要多出来一个 \(a_x\times b_{fa_x}\) 的贡献。
直接并查集维护。。
code
#include <bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Failed"
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=5e6+10;
int n,ans,cnt,sum,fa[N],fat[N],a[N],b[N];
bool vis[N],jud[N];
struct Node
{
int id;
inline bool friend operator < (Node x,Node y)
{
return b[x.id]*a[y.id]<b[y.id]*a[x.id];
}
};
priority_queue<Node> q;
int find(int x)
{
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
signed main()
{
freopen("data.in","r",stdin); freopen("data.out","w",stdout);
n=read(); vis[0]=true; cnt=n;
for(int i=2;i<=n;i++) fat[i]=read();
for(int i=1;i<=4*n;i++) fa[i]=i;
for(int i=1;i<=n;i++) a[i]=read(),b[i]=read(),sum+=a[i];
for(int i=1;i<=n;i++) q.push((Node){i});
while(!q.empty())
{
int x=q.top().id; q.pop();
if(jud[x]) continue;
if(!vis[find(fat[x])])
{
ans+=a[x]*b[find(fat[x])]; cnt++;
a[cnt]=a[x]+a[find(fat[x])];
b[cnt]=b[x]+b[find(fat[x])];
jud[find(fat[x])]=true;
fat[cnt]=fat[find(fat[x])];
fa[find(fat[x])]=fa[x]=cnt;
q.push((Node){cnt});
continue;
}
sum-=a[x];
ans+=sum*b[x];
vis[x]=true;
}
printf("%lld",ans);
return 0;
}
T2 下落的小球
解题思路
听 fengwu 说好像和移球游戏的思路有一点像...
对于一颗子树而言它的球一定不会掉在子树外。
因此有子树根节点下来的小球的数量也是一定的,并且两者操作有先后顺序,因此就是两个多重集排列。
对于每一个不同的节点计算对于答案的贡献。
code
#include <bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Failed"
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=1e6+10,mod=1e9+7;
int n,ans=1,fa[N],siz[N],cnt[N],fac[N],ifac[N];
int tot=1,head[N],ver[N<<1],nxt[N<<1];
void add_edge(int x,int y)
{
ver[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
int power(int x,int y,int p=mod)
{
int temp=1;
while(y)
{
if(y&1) temp=temp*x%p;
x=x*x%p; y>>=1;
}
return temp;
}
void dfs(int x)
{
int temp=0;
for(int i=head[x];i;i=nxt[i])
{
int to=ver[i]; dfs(to);
siz[x]+=siz[to]; cnt[x]+=cnt[to];
ans=ans*ifac[siz[to]]%mod*ifac[cnt[to]-siz[to]]%mod;
}
if(head[x]) ans=ans*fac[siz[x]]%mod*fac[cnt[x]-siz[x]]%mod; siz[x]++;
}
signed main()
{
freopen("ball.in","r",stdin); freopen("ball.out","w",stdout);
n=read(); fac[0]=ifac[0]=1;
for(int i=2;i<=n;i++) fa[i]=read(),add_edge(fa[i],i);
for(int i=1;i<=n;i++) cnt[i]=read();
for(int i=1;i<=n;i++) fac[i]=fac[i-1]*i%mod;
ifac[n]=power(fac[n],mod-2);
for(int i=n-1;i>=1;i--) ifac[i]=ifac[i+1]*(i+1)%mod;
dfs(1); printf("%lld",ans);
return 0;
}
T3 消失的运算符
大坑未补
T4 古老的序列问题
解题思路
分治,对于每一个子区间计算对于每一个询问答案。
维护四颗线段树,分别给加进去的值乘上 1,min,max,min*max
先处理左区间的最大值最小值,然后对于左区间建线段树,暴扫右区间三指针分别扫出来满足最小值条件,最大值条件,同时满足的区间。
分别计算在相应问题区间贡献,同时开一个数组记录一下这个区间的贡献,解决问题区间覆盖整个子区间的答案。
code
#include <bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Failed"
#define ls x<<1
#define rs x<<1|1
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=1e5+10,mod=1e9+7;
int n,m,s[N],ans[N],f[N<<2],minn[N],maxn[N];
inline void add(int &x,int val){x+=val;if(x>=mod)x-=mod;}
struct Node
{
int l,r,id;
inline bool friend operator < (Node x,Node y){return x.r<y.r;}
};
vector<Node> v[N<<2];
struct Segment_Tree
{
int num[N];
struct Node{int dat,laz,bas;}tre[N<<2];
inline void push_up(int x){tre[x].dat=(tre[ls].dat+tre[rs].dat)%mod;}
inline void push_down(int x)
{
if(!tre[x].laz) return ;
add(tre[ls].laz,tre[x].laz); add(tre[ls].dat,tre[x].laz*tre[ls].bas%mod);
add(tre[rs].laz,tre[x].laz); add(tre[rs].dat,tre[x].laz*tre[rs].bas%mod);
tre[x].laz=0;
}
inline void build(int x,int l,int r)
{
tre[x].laz=tre[x].dat=0;
if(l==r) return tre[x].bas=num[l],void();
int mid=(l+r)>>1; build(ls,l,mid); build(rs,mid+1,r);
tre[x].bas=(tre[ls].bas+tre[rs].bas)%mod;
}
inline void insert(int x,int l,int r,int L,int R,int val)
{
if(L<=l&&r<=R) return add(tre[x].dat,tre[x].bas*val%mod),add(tre[x].laz,val),void();
int mid=(l+r)>>1; push_down(x);
if(L<=mid) insert(ls,l,mid,L,R,val);
if(R>mid) insert(rs,mid+1,r,L,R,val);
push_up(x);
}
inline int query(int x,int l,int r,int L,int R)
{
if(L<=l&&r<=R) return tre[x].dat;
int mid=(l+r)>>1,sum=0; push_down(x);
if(L<=mid) add(sum,query(ls,l,mid,L,R));
if(R>mid) add(sum,query(rs,mid+1,r,L,R));
push_up(x); return sum;
}
}T[4];
void solve(int pos,int l,int r)
{
if(l==r)
{
f[pos]=s[l]*s[l]%mod;
for(int i=0;i<v[pos].size();i++) add(ans[v[pos][i].id],f[pos]);
return ;
}
int mid=(l+r)>>1,poi=0,x=mid+1,y=mid+1,z=mid+1,mx=s[mid+1],mn=s[mid+1];
sort(v[pos].begin(),v[pos].end()); maxn[mid]=minn[mid]=s[mid];
while(poi<v[pos].size()&&v[pos][poi].r<=mid) poi++;
for(int i=mid-1;i>=l;i--) minn[i]=min(minn[i+1],s[i]),maxn[i]=max(maxn[i+1],s[i]);
fill(T[0].num+l,T[0].num+mid+1,1);
for(int i=l;i<=mid;i++) T[1].num[i]=maxn[i],T[2].num[i]=minn[i],T[3].num[i]=maxn[i]*minn[i]%mod;
for(int i=0;i<=3;i++) T[i].build(1,l,mid);
for(int i=mid+1;i<=r;i++)
{
mx=max(mx,s[i]); mn=min(mn,s[i]);
while(x>l&&minn[x-1]>=mn&&maxn[x-1]<=mx) x--;
while(y>l&&minn[y-1]>=mn) y--;
while(z>l&&maxn[z-1]<=mx) z--;
if(x<=mid) T[0].insert(1,l,mid,x,mid,mx*mn%mod);
if(y<x) T[1].insert(1,l,mid,y,x-1,mn);
if(z<x) T[2].insert(1,l,mid,z,x-1,mx);
if(y<x&&y>l) T[3].insert(1,l,mid,l,y-1,1);
if(z<x&&z>l) T[3].insert(1,l,mid,l,z-1,1);
while(poi<v[pos].size()&&v[pos][poi].r==i)
if(v[pos][poi].l>mid||(v[pos][poi].l==l&&v[pos][poi].r==r)) poi++;
else{for(int j=0;j<=3;j++) add(ans[v[pos][poi].id],T[j].query(1,l,mid,v[pos][poi].l,mid));poi++;}
}
for(int i=0;i<=3;i++) add(f[pos],T[i].query(1,l,mid,l,mid));
for(int i=0;i<v[pos].size();i++)
{
if(v[pos][i].l==l&&v[pos][i].r==r) continue;
if(v[pos][i].r<=mid) v[pos<<1].push_back(v[pos][i]);
else if(v[pos][i].l>mid) v[pos<<1|1].push_back(v[pos][i]);
else
{
v[pos<<1].push_back((Node){v[pos][i].l,mid,v[pos][i].id});
v[pos<<1|1].push_back((Node){mid+1,v[pos][i].r,v[pos][i].id});
}
}
solve(pos<<1,l,mid); solve(pos<<1|1,mid+1,r);
add(f[pos],(f[pos<<1]+f[pos<<1|1])%mod);
for(int i=0;i<v[pos].size();i++)
if(v[pos][i].l==l&&v[pos][i].r==r)
add(ans[v[pos][i].id],f[pos]);
}
signed main()
{
freopen("sequence.in","r",stdin); freopen("sequence.out","w",stdout);
n=read(); m=read(); for(int i=1;i<=n;i++) s[i]=read();
for(int i=1,l,r;i<=m;i++) l=read(),r=read(),v[1].push_back((Node){l,r,i});
solve(1,1,n); for(int i=1;i<=m;i++) printf("%lld\n",ans[i]);
return 0;
}
NOIP模拟67的更多相关文章
- Noip模拟67 2021.10.3
还是困,不过已经可以用脑子思考问题了 T1 数据恢复 没啥明确的算法,可以说是贪心? 考虑部分分, 链的直接扫, 对于菊花的发现只要根节点在第一个,剩下的点位置不重要 那么按照$a/b$排序,扫一遍就 ...
- NOIP模拟17.9.22
NOIP模拟17.9.22 前进![问题描述]数轴的原点上有一只青蛙.青蛙要跳到数轴上≥
- NOIP 模拟4 T2
本题属于二和一问题 子问题相互对称 考虑对于问题一:知a求b 那么根据b数组定义式 显然能发现问题在于如何求dis(最短路) 有很多算法可供选择 dijsktra,floyed,bfs/dfs,spf ...
- noip模拟32[好数学啊]
noip模拟32 solutions 真是无语子,又没上100,无奈死了 虽然我每次都觉得题很难,但是还是有好多上100的 战神都200多了,好生气啊啊啊 从题开始变难之后,我的时间分配越来越不均匀, ...
- 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 ...
- contesthunter暑假NOIP模拟赛第一场题解
contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...
- NOIP模拟赛 by hzwer
2015年10月04日NOIP模拟赛 by hzwer (这是小奇=> 小奇挖矿2(mining) [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿 ...
- 大家AK杯 灰天飞雁NOIP模拟赛题解/数据/标程
数据 http://files.cnblogs.com/htfy/data.zip 简要题解 桌球碰撞 纯模拟,注意一开始就在袋口和v=0的情况.v和坐标可以是小数.为保险起见最好用extended/ ...
- 队爷的讲学计划 CH Round #59 - OrzCC杯NOIP模拟赛day1
题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的讲学计划 题解:刚开始理解题意理解了好半天,然后发 ...
随机推荐
- c# 优化代码的一些规则——判断null值得不同写法[六]
前言 先来看一个例子: 假设updated 是一个委托: if(updated!=null) { updated(); } 请问上面写法在多线程中安全吗?如果不安全会抛出什么异常呢? 正文 上面的答案 ...
- KubeOperator技术方案
KubeOperator技术方案 总体介绍︎ KubeOperator 是一个开源的轻量级 Kubernetes 发行版,专注于帮助企业规划.部署和运营生产级别的 Kubernetes 集群. Kub ...
- 中国大陆地区维护的Linux操作系统
Linux开源生态丰富,中国大陆地区基于CentOS停服,依托阿里云.腾讯云.华为云三大私营企业,相继发布了自己的开源Linux定制版,很高兴的是他们只是改个名字并没有选择闭门造车,只是官网还是很不耻 ...
- GaussDB SQL查询语句执行过程解析
本文分享自华为云社区<[GaussTech第2期]GaussDB SQL查询语句执行过程解析>,作者: GaussDB 数据库. SQL于关系型数据库而言,重要性不言而喻.就像一个乐团的指 ...
- 新零售标杆 SKG 全面拥抱 Serverless,实现敏捷交付
简介: SKG CTO 王焱:以前需要 60 个人干的活,用 SAE 和大禹后 15 个人就可以! 作者:陈列昂.昕辰.龙琛.黛忻 项目背景 SKG 公司是一家专注于高端健康产品的研发.设计与制造 ...
- 深入理解C++中的RVO
前言 考虑存在这样一个类如HeavyObject,其拷贝赋值操作比较耗时,通常你在使用函数返回这个类的一个对象时会习惯使用哪一种方式?或者会根据具体场景选择某一种方式? // style 1 Heav ...
- 为余势负天工背,云原生内存数据库Tair助力用户体验优化
简介:作为双11大促承载流量洪峰的利器,Tair支撑了电商交易核心体验场景.不仅在数十亿QPS的峰值下保持着亚毫秒级别的顺滑延迟,同时在电商交易核心体验场景上也做出了技术创新. 作者 | 漠冰 ...
- [Pholcus] Go项目 Pholcus 编写静态规则文件, 0 到 1
1. 初始化项目包,go mod init [module-path] 比如:go mod init github.com/abc/efg 2. 新建一个目录放置我们编写的规则 go 文件. 3. m ...
- WinForm 下的高性能笔迹方法
在 WPF 中可以通过 StylusPlugIn 的方式快速从触摸线程拿到触摸数据,而 WinForms 没有这个机制,但是可以通过 Microsoft.Ink 组件和 WPF 相同在 RealTim ...
- 深入理解 C++ 中的多态与文件操作
C++ 多态 多态(Polymorphism)是面向对象编程(OOP)的核心概念之一,它允许对象在相同操作下表现出不同的行为.在 C++ 中,多态通常通过继承和虚函数来实现. 理解多态 想象一个场景, ...