得分: \(100+10+45=155\)(\(T1\)又是水题,\(T2\)写暴力,\(T3\)大力\(STL\)乱搞)

\(T1\):哈夫曼树

首先,根据题目中给出的式子,可以发现,我们要求的其实就是每种方案下的总代价和。

显然,每个数被选择的总次数应该是相同的。

因此,我们可以设\(f_i\)为在还剩下\(i\)个数时进行操作后,每个数被选择的次数

则易推得转移方程:

\[f_i=\frac{i(i-1)}2*f_{i+1}+(i-1)\prod_{j=i+1}^n\frac{j(j-1)}2
\]

对于这个式子,我们可以这样考虑:

  • 由于每一次合并时每个数被选择的次数是可以独立计算的,所以,我们可以直接通过\(\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模拟赛 解题报告的更多相关文章

  1. 2019.03.16 ZJOI2019模拟赛 解题报告

    得分: \(100+27+20=147\)(\(T1\)巨水,\(T2,T3\)只能写暴力分) \(T1\):深邃 比较套路的一眼题,显然是一个二分+贪心,感觉就是\(NOIP2018Day1T3\) ...

  2. 2019.03.02 ZJOI2019模拟赛 解题报告

    得分: \(10+0+40=50\)(\(T1\),\(T3\)只能写大暴力,\(T2\)压根不会) \(T1\):道路建造 应该是一道比较经典的容斥题,可惜比赛时没有看出来. 由于要求最后删一条边或 ...

  3. 2019.03.09 ZJOI2019模拟赛 解题报告

    得分: \(20+0+40=60\)(\(T1\)大暴力,\(T2\)分类讨论写挂,\(T3\)分类讨论\(40\)分) \(T1\):天空碎片 一道神仙数学题,貌似需要两次使用中国剩余定理. 反正不 ...

  4. 2019.03.13 ZJOI2019模拟赛 解题报告

    得分: \(55+12+10=77\)(\(T1\)误认为有可二分性,\(T2\)不小心把\(n\)开了\(char\),\(T3\)直接\(puts("0")\)水\(10\)分 ...

  5. 2019.03.14 ZJOI2019模拟赛 解题报告

    得分: \(100+100+0=200\)(\(T1\)在最后\(2\)分钟写了出来,\(T2\)在最后\(10\)分钟写了出来,反而\(T3\)写了\(4\)个小时爆\(0\)) \(T1\):风王 ...

  6. 2019.03.15 ZJOI2019模拟赛 解题报告

    得分: \(20+45+15=80\)(三题暴力全写挂...) \(T1\):Lyk Love painting 首先,不难想到二分答案然后\(DP\)验证. 设当前需验证的答案为\(x\),则一个暴 ...

  7. 10.30 NFLS-NOIP模拟赛 解题报告

    总结:今天去了NOIP模拟赛,其实是几道USACO的经典的题目,第一题和最后一题都有思路,第二题是我一开始写了个spfa,写了一半中途发现应该是矩阵乘法,然后没做完,然后就没有然后了!第二题的暴力都没 ...

  8. 20201101gryz模拟赛解题报告

    写在前面 2020rp++ 停课的第一场模拟赛 拿上一年的上一年的day1来考的, 结果得分期望220pts,实际135pts,rank3,太菜了 考着考着机房灯突然灭了,当时慌的一批 以为断电代码要 ...

  9. 2018.10.26NOIP模拟赛解题报告

    心路历程 预计得分:\(100 + 100 + 70\) 实际得分:\(40 + 100 + 70\) 妈妈我又挂分了qwq..T1过了大样例就没管,直到临考试结束前\(10min\)才发现大样例是假 ...

随机推荐

  1. Python学习 day03

    一.基本数据类型 python中的基本数据类型有以下几种: int   --  整数     python3中默认整数都是int型,python2中int的范围为-231~232-1(32位系统中)/ ...

  2. 有关tensorflow一些问题

    1.python版本 采用64位的python 2.系统不支持高版本tensorflow(>1.6),运行报错如下: 问题描述如下: ImportError: DLL load failed: ...

  3. RabbitMQ原理——exchange、route、queue的关系

    从AMQP协议可以看出,MessageQueue.Exchange和Binding构成了AMQP协议的核心,下面我们就围绕这三个主要组件    从应用使用的角度全面的介绍如何利用Rabbit MQ构建 ...

  4. 移动端刷新组件XtnScroll--Angular4实现

    刷新组件 - 主要是学习一下Angular4所有花了我一天时间,写了这个刷新组件. 以项目开发当中,特别是手机移动端开发的时候,经常要用到就是上拉加载下一面,下拉刷新获取最新数据的功能. 在网也有很多 ...

  5. AWS and OpenStack

    AWS OpenStack EC2 Nova EBS Cinder EFS Manila S3 Swift Storage Gateway 本地上云 ClondFront 内容发布服务 VPC Neu ...

  6. vim代码折叠命令

    1. 折叠方式 可用选项 'foldmethod' 来设定折叠方式:set fdm=*****. 有 6 种方法来选定折叠:           manual           手工定义折叠 ind ...

  7. HDU 2795——Billboard——————【单点更新、求最小位置】

    Billboard Time Limit:8000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit St ...

  8. Java学习第十八天

    1:Map(掌握) (1)将键映射到值的对象.一个映射不能包含重复的键:每个键最多只能映射到一个值. (2)Map和Collection的区别? A:Map 存储的是键值对形式的元素,键唯一,值可以重 ...

  9. 3.storm-starter打包在storm集群上运行

    1.使用maven或者其他打包工具将storm-starter打成jar包 2.请将jar包用解压工具打开在根目录下找到defaults.yaml文件并将其删除不然到时会报有multiply defa ...

  10. 从零开始的全栈工程师——JS面向对象(复习)

    作用域 栈内存:js执行的环境堆内存:存放代码块的空间 存放方式 键值对形式存放 字符串的形式存放js在执行之前 浏览器会给他一个全局作用域叫window 每个作用域下都分为两个模块 一个是内存模块一 ...