2019.03.19 ZJOI2019模拟赛 解题报告
得分: \(100+10+45=155\)(\(T1\)又是水题,\(T2\)写暴力,\(T3\)大力\(STL\)乱搞)
\(T1\):哈夫曼树
首先,根据题目中给出的式子,可以发现,我们要求的其实就是每种方案下的总代价和。
显然,每个数被选择的总次数应该是相同的。
因此,我们可以设\(f_i\)为在还剩下\(i\)个数时进行操作后,每个数被选择的次数。
则易推得转移方程:
\]
对于这个式子,我们可以这样考虑:
- 由于每一次合并时每个数被选择的次数是可以独立计算的,所以,我们可以直接通过\(\frac{i(i-1)}2*f_{i+1}\)这个式子来计算之前的总贡献。(即上一步每个数被选择的次数乘从上一步到这一步的转移方案数)
- 而当前,这个数被选择的方案数为\(i-1\),即选择包含这个数的位置和其余\(i-1\)个位置中的任意一个位置合并。由于还剩\(i\)个数的方案数共有\(\prod_{j=i+1}^n\frac{j(j-1)}2\)种,因此当前的贡献就是\((i-1)\prod_{j=i+1}^n\frac{j(j-1)}2\)。
还有一点要注意的,就是最后总方案数为\(f_2\)。
然后将\(f_2\)乘上数的总和,就是答案了。
代码如下:
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100000
#define X 1000000007
#define Inc(x,y) ((x+=(y))>=X&&(x-=X))
#define Dec(x,y) ((x-=(y))<0&&(x+=X))
#define XSum(x,y) ((x)+(y)>=X?(x)+(y)-X:(x)+(y))
using namespace std;
int n,a[N+5];
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define tn (x<<3)+(x<<1)
#define D isdigit(c=tc())
char c,*A,*B,FI[FS];
public:
I FastIO() {A=B=FI;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
}F;
class DpSolver
{
private:
#define S(x) ((1LL*(x)*((x)-1)>>1)%X)
int f[N+5];
public:
I int GetAns()
{
RI i,j,t=1,sum=0;for(i=n;i^1;--i)//枚举状态进行转移
f[i]=XSum(1LL*S(i)*f[i+1]%X,1LL*(i-1)*t%X),t=1LL*S(i)*t%X;
for(i=1;i<=n;++i) Inc(sum,a[i]);return 1LL*f[2]*sum%X;//输出答案
}
}DP;
int main()
{
freopen("huffman.in","r",stdin),freopen("huffman.out","w",stdout);
RI i;for(F.read(n),i=1;i<=n;++i) F.read(a[i]);return printf("%d",DP.GetAns()),0;
}
\(T2\):线段树
首先,可以发现一个比较显然的性质:最后查询的这个数的值肯定是一段连续区间的最大值。
则我们所要做的,就是求出这段区间,然后最大值就很好求了。
考虑对当前询问的数,我们找到在它之前最靠近它且包含它的一个区间,然后再去寻找与这个区间有重叠的其他区间,最后就能扩展成一个很大的区间。
那我们能不能从前往后正着进行一遍这样的过程呢?
显然可以。
我们可以定义\(f1_i\)和\(f2_i\),分别表示满足\(j<i\)且\(L_j\le L_i\le R_j\)的最大\(j\)和满足\(j<i\)且\(L_j\le R_i\le R_j\)的最大\(j\)。
这就相当于分别求出最靠近该区间且与该区间有重叠的左边和右边的区间。
这一过程可以直接用线段树,但因为后面的某些特殊需求,因此需要主席树。
则不难发现,对于第\(i\)个区间,它的答案会受到\(f1_i\)和\(f2_i\)两个区间的影响,而\(f1_i\)和\(f2_i\)又会受到各自的\(f1\)和\(f2\)的影响。
如果我们考虑吧\(f1_i\)和\(f2_i\)分别看作\(i\)的父亲,就可以建出两棵树。
而对于一次询问,我们就可以像前面说的那样,在\([l,r]\)范围内找到在它之前最靠近它且包含它的一个区间(这里就需要使用主席树了),然后在两棵树中分别倍增向上跳,分别找到最远的且大于等于\(l\)的操作,然后就能确定出会影响当前位置的区间范围了。
再就相当于线段树上询问区间最大值了。
代码如下:
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100000
#define Log 20
#define max(x,y) ((x)>(y)?(x):(y))
#define Gmax(x,y) (x<(y)&&(x=(y)))
using namespace std;
int n,m,a[N+5],b[N+5],ql[N+5],qr[N+5],f1[N+5][Log+5],f2[N+5][Log+5];
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define pc(c) (C^FS?FO[C++]=c:(fwrite(FO,1,C,stdout),FO[(C=0)++]=c))
#define tn (x<<3)+(x<<1)
#define D isdigit(c=tc())
int T,C;char c,*A,*B,FI[FS],FO[FS],S[FS];
public:
I FastIO() {A=B=FI;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
Tp I void writeln(Con Ty& x) {write(x),pc('\n');}
I void clear() {fwrite(FO,1,C,stdout),C=0;}
}F;
class ChairmanTree//主席树
{
private:
#define STO l,hl,O[rt].S[0]
#define ORZ hl+1,r,O[rt].S[1]
#define PD(x) (O[x].S[0]&&Gmax(O[O[x].S[0]].V,O[x].V),O[x].S[1]&&Gmax(O[O[x].S[1]].V,O[x].V))
int v,tot,Rt[N+5];struct Il {int V,S[2];}O[N*Log<<2];
I void ins(CI l,CI r,int& rt,CI lst,CI ul,CI ur,CI w)//插入新节点,区间修改,维护最靠近某个节点且包含它的一个区间
{
if(O[rt=++tot]=O[lst],ul<=l&&r<=ur) return
(void)(Gmax(O[rt].V,w),O[rt].S[0]=++tot,O[rt].S[1]=++tot);
PD(rt);RI hl=l+r>>1;ul<=hl&&(ins(STO,O[lst].S[0],ul,ur,w),0),
ur>hl&&(ins(ORZ,O[lst].S[1],ul,ur,w),0);
}
I int qry(CI l,CI r,CI rt,CI x)//询问
{
if(!x||!(l^r)) return O[rt].V;PD(rt);RI hl=l+r>>1,res;
return res=(x<=hl?qry(STO,x):qry(ORZ,x)),max(O[rt].V,res);
}
public:
I void Insert(CI l,CI r,CI w) {++v,ins(1,n,Rt[v],Rt[v-1],l,r,w);}
I int Query(CI t,CI x) {return qry(1,n,Rt[t],x);}
}C;
class SegmentTree//线段树
{
private:
#define STO l,hl,rt<<1
#define ORZ hl+1,r,rt<<1|1
#define PU(x) (V[x]=max(V[x<<1],V[x<<1|1]))
int n,v[N+5],V[N<<2];
I void Build(CI l,CI r,CI rt)//初始化建树
{
if(!(l^r)) return (void)(V[rt]=v[l]);RI hl=l+r>>1;
Build(STO),Build(ORZ),PU(rt);
}
I void upt(RI l,RI r,RI rt,CI x,CI y)//单点修改,这里用了非递归实现
{
RI hl;W(l^r) hl=l+r>>1,x<=hl?(r=hl,rt<<=1):(l=hl+1,(rt<<=1)|=1);
V[rt]=y;W(rt>>=1) PU(rt);
}
I int qry(CI l,CI r,CI rt,CI ql,CI qr)//区间求最大值
{
if(ql<=l&&r<=qr) return V[rt];RI hl=l+r>>1,res=0,t;
return ql<=hl&&(t=qry(STO,ql,qr),Gmax(res,t)),qr>hl&&(t=qry(ORZ,ql,qr),Gmax(res,t)),res;
}
public:
I void Init(CI x,int* s) {for(RI i=1;i<=x;++i) v[i]=s[i];Build(1,n=x,1);}
I void Update(CI x,CI y) {upt(1,n,1,x,y);}
I int Query(CI x,CI y) {return qry(1,n,1,x,y);}
}S;
I void Pre()//初始化
{
RI i,j;for(i=1;i<=m;++i) f1[i][0]=C.Query(i-1,ql[i]),//扫一遍,初始化主席树,同时求出f1与f2
f2[i][0]=C.Query(i-1,qr[i]),C.Insert(ql[i],qr[i],i);
for(j=1;j<=Log;++j) for(i=1;i<=n;++i)//预处理倍增数组
f1[i][j]=f1[f1[i][j-1]][j-1],f2[i][j]=f2[f2[i][j-1]][j-1];
}
int main()
{
freopen("segment.in","r",stdin),freopen("segment.out","w",stdout);
RI Qtot,i,op,x,y,z,fl,fr;for(F.read(n,m,Qtot),i=1;i<=n;++i) F.read(a[i]);//读入数据
for(i=1;i<=m;++i) F.read(ql[i],qr[i]);Pre(),S.Init(n,a);W(Qtot--)//读入数据,预处理
{
if(F.read(op,x,y),op^2) {a[x]=y,S.Update(x,y);continue;}//单点修改
if(F.read(z),(fl=fr=C.Query(y,z))<x) {F.writeln(a[z]);continue;}//求出最靠近当前点且包含当前点的区间,若编号小于x,则直接输出这一位上的值
for(i=Log;~i;--i) f1[fl][i]>=x&&(fl=f1[fl][i]),f2[fr][i]>=x&&(fr=f2[fr][i]);//倍增向上跳,求出对当前位置有影响的区间
F.writeln(S.Query(ql[fl],qr[fr]));//输出答案
}return F.clear(),0;
}
\(T3\):接水问题
\(STL\)大暴力,水了\(45\)分。
不会订正,待补。
2019.03.19 ZJOI2019模拟赛 解题报告的更多相关文章
- 2019.03.16 ZJOI2019模拟赛 解题报告
得分: \(100+27+20=147\)(\(T1\)巨水,\(T2,T3\)只能写暴力分) \(T1\):深邃 比较套路的一眼题,显然是一个二分+贪心,感觉就是\(NOIP2018Day1T3\) ...
- 2019.03.02 ZJOI2019模拟赛 解题报告
得分: \(10+0+40=50\)(\(T1\),\(T3\)只能写大暴力,\(T2\)压根不会) \(T1\):道路建造 应该是一道比较经典的容斥题,可惜比赛时没有看出来. 由于要求最后删一条边或 ...
- 2019.03.09 ZJOI2019模拟赛 解题报告
得分: \(20+0+40=60\)(\(T1\)大暴力,\(T2\)分类讨论写挂,\(T3\)分类讨论\(40\)分) \(T1\):天空碎片 一道神仙数学题,貌似需要两次使用中国剩余定理. 反正不 ...
- 2019.03.13 ZJOI2019模拟赛 解题报告
得分: \(55+12+10=77\)(\(T1\)误认为有可二分性,\(T2\)不小心把\(n\)开了\(char\),\(T3\)直接\(puts("0")\)水\(10\)分 ...
- 2019.03.14 ZJOI2019模拟赛 解题报告
得分: \(100+100+0=200\)(\(T1\)在最后\(2\)分钟写了出来,\(T2\)在最后\(10\)分钟写了出来,反而\(T3\)写了\(4\)个小时爆\(0\)) \(T1\):风王 ...
- 2019.03.15 ZJOI2019模拟赛 解题报告
得分: \(20+45+15=80\)(三题暴力全写挂...) \(T1\):Lyk Love painting 首先,不难想到二分答案然后\(DP\)验证. 设当前需验证的答案为\(x\),则一个暴 ...
- 10.30 NFLS-NOIP模拟赛 解题报告
总结:今天去了NOIP模拟赛,其实是几道USACO的经典的题目,第一题和最后一题都有思路,第二题是我一开始写了个spfa,写了一半中途发现应该是矩阵乘法,然后没做完,然后就没有然后了!第二题的暴力都没 ...
- 20201101gryz模拟赛解题报告
写在前面 2020rp++ 停课的第一场模拟赛 拿上一年的上一年的day1来考的, 结果得分期望220pts,实际135pts,rank3,太菜了 考着考着机房灯突然灭了,当时慌的一批 以为断电代码要 ...
- 2018.10.26NOIP模拟赛解题报告
心路历程 预计得分:\(100 + 100 + 70\) 实际得分:\(40 + 100 + 70\) 妈妈我又挂分了qwq..T1过了大样例就没管,直到临考试结束前\(10min\)才发现大样例是假 ...
随机推荐
- libevent 同性恋 讲解
https://aceld.gitbooks.io/libevent/content/25hong_fa_mo_5f0f_md.html github 这url 干活比较好 https://githu ...
- Thinkphp基于规则的Auth权限认证类
PS:onethink是基于该权限认证类实现,Auth类作为官方类库,在Library\Think里面. 其实Auth类也是基于角色访问控制RBAC扩展的,具体到节点的权限校验方式还是需要根据业务 ...
- Python 中数据的序列化和反序列化(json处理)
概念: JSON(JavaScript Object Notation):是一种轻量级的数据交换格式. 易于人阅读和编写.同时也易于机器解析和生成. 它基于JavaScript Programming ...
- 第十八章:自定义splash screen、app icon和tab icon
本文介绍如何自定义splash screen.app icon和tab icon. 1. 自定义splash screen和app icon 1.1 产生resources文件夹,启动命令行: ion ...
- Hadoop Ecosytem
There are a lot of Hadoop related projects which are open sourced and widely used by many componies. ...
- java中的各种修饰符作用范围
访问修饰符: private 缺省 protected public 作用范围: 访问修饰符\作用范围 所在类 同一包内其他类 其他包内子类 其他包内非子类 private 可以访问 不可以 不可以 ...
- Windows与Unix思想
Unix与Windows的思想 Unix中的哲学是"一切皆文件",这里的一切皆文件是一个广泛的概念,有一些特殊的设备文件,在/dev目录下 物理设备在Unix中就对应一个特殊的设备 ...
- Whu 1604——Play Apple——————【博弈】
Problem 1604 - Play Apple Time Limit: 1000MS Memory Limit: 65536KB Total Submit: 442 Accepted: ...
- Linux systemd资源控制初探
Linux systemd资源控制初探 本文记录一次cgroup子目录丢失问题,并简单探索了Linux systemd的资源控制机制. 问题现象 我们希望通过systemd拉起服务并通过cgroup限 ...
- spring cloud Eureka 服务注册发现与调用
记录一下用spring cloud Eureka搭建服务注册与发现框架的过程. 为了创建spring项目方便,使用了STS. 一.Eureka注册中心 1.新建项目-Spring Starter Pr ...