复习与回顾:2021.7.11 contest 4

复习与回顾:2021.7.11 contest 4

A

Description

​ 有 \(n\) 只青蛙,第 \(i\) 只青蛙会每过 \(x_i\) 秒会连续叫 \(y_i\) 秒。然而由于青蛙的寿命在增加,所以从第二次开始每次休息结束后这只青蛙连续叫的时间会增加 \(z_i\) 秒。
​ 给定 \(n\) 只青蛙,每一只的 \(z_i,y_i,z_i\) ,以及时间 \(t\) ,求在前 \(t\) 秒中,所有青蛙共叫了多少秒。

Input

​ 第一行两个数 \(n\)\(t\)

​ 之后 \(n\) 行,第 \(i\) 行每行三个非负整数 \(x_i,y_i,z_i\)

Output

​ 一行一个数表示答案。

Example

input 1
8 10
9 1 1
1 9 9
4 1 0
2 3 3
1 0 0
1 4 0
9 2 5
1 2 1
output 1
34
input 2
1 233333
233 233 233
output 2
223081
input 3
10 100000000
1 0 0
1 0 5
1 2 2
1 2 8
1 3 0
1 5 0
1 5 2
1 5 5
1 7 0
1 8 3
output 3
845787522

Hint

​ 满足 \(1 \leq n \leq 10^5\ ,\ t \leq 2 *10^9\ ,\ x+y+z>0\ ,\ 0 \leq x_i,y_i,z_i \leq 2 *10^9\)

Solution

​ 注意下 \(x+y+z\) 可能爆 \(int\)

Code
long long Ans;
int n,tim;
int calc(int X,int Y,int Z,int T){
	if((X+Y+X+Y+1ll*(T-1)*Z)>2e9)return -1;
	if(1ll*T*(X+Y+X+Y+1ll*(T-1)*Z)>4e9)return -1;
	long long res=1ll*T*(X+Y+X+Y+1ll*(T-1)*Z);return res/2;
}
void work(){
	int X,Y,Z;Read(X);Read(Y);Read(Z);
	//二分计算完整x->y->z的次数,其实可以O(1),然而懒得动脑了
	int l=1,r=2e9,mid;
	while(l<=r){
		mid=(l+r)>>1;
		int tmp=calc(X,Y,Z,mid);
		if(tmp!=-1&&tmp<=tim)
		l=mid+1;else r=mid-1;
	}
	int T=calc(X,Y,Z,r);
	long long ADD=T-1ll*r*X+max(0,tim-T-X);
	Ans+=ADD;
}
int main(){
	Read(n);Read(tim);
	for(int i=1;i<=n;i++)work();
	cout<<Ans<<'\n';
	return 0;
}

B

Description

​ 有一款游戏叫坦克世界,也叫作脚本世界。

​ 坦克有各种炮弹,比如 AP,APC,APCBC,APCR,APCNR,APBC,APDS,APFSDS,HEAT,HEATFS,HE,HESH,HVAP......

​ 为了简化游戏,我们只考虑全口径穿甲弹 AP (Armor Piercing) 与高爆榴弹 HE (High Explosive)。

​ 每种炮弹有一个标准伤害值,当炮弹击中敌人,会由以下方法计算伤害:

​ AP : 如果击穿了敌人的装甲,则敌人会受到该炮弹的标准伤害值大小的伤害,如果我们未能击穿敌人的装甲,则敌人不受到任何伤害。
​ HE : 如果击穿了敌人的装甲,则敌人会受到该炮弹的标准伤害值大小的伤害,如果我们未能击穿敌人的装甲,则敌人会受到一个在 \([0\ ,\ 0.5*\text{标准伤害值}]\) 中均匀随机的整数伤害值。

​ 游戏有一个特性,因为 HE 炮弹的装药一般都比 AP 多(要是比 AP 还少那实在是没救了),所以 HE 炮弹的标准伤害值大于 AP 炮弹的标准伤害值。

​ 在上一局游戏中,nzhtl1477 发射了 \(n\) 发炮弹,但是不知道这些炮弹是否有击穿敌人或者击中敌人,请问该玩家是否可能造成了总共 \(m\) 点伤害?

Input

​ 输入包含多组数据,第一行输入一个 \(t\) 表示数据组数。
​ 之后 \(t\) 行,每行四个数 \(n,m,a,b\) ,其中 \(n,m\) 的意义如上述,\(a\) 表示 AP 的标准伤害值,\(b\) 表示 HE 的标准伤害值。保证 \(a<b\)\(a\)\(b\) 均为正整数,所有数均为整数。

Output

​ 输出 \(t\) 行,对每组数据,如果可以,输出 "Yes",否则输出 "No"(均不带括号)。

Example

input
10
1 3 4 5
1 4 4 5
1 5 4 5
2 7 4 5
2 8 4 5
2 9 4 5
2 10 4 5
2 11 4 5
114 514 2 4
114 514 2 5
output
No
Yes
Yes
Yes
Yes
Yes
Yes
No
No
Yes

Hint

​ 满足 \(1 \leq t \leq 10^6\ ,\ 0 \leq n,m \leq 10^{18}\ ,\ 1 \leq a < b \leq 10^{18}\)

Solution

​ 首先若 \(b*n<m\)​ 一定无解,若 \(b*n=m\) 一定有解,只需考虑 \(b*n > m\)

​ 令 \(c= \lfloor \frac{b}{2} \rfloor\)​​ 则 \(c*2 \geq b-1\)​​​​ ,若 \(\lfloor \frac{m}{b} \rfloor =n-1\ \ \ \bigwedge\ \ \ m\ \ mod\ \ b > c\)​​​​​ 则​​​不存在有跳弹情况的解,否则一定存在一个HE跳弹若干次的解。而此时存在不跳弹的解当且仅当 $a*n \leq m\ \bigwedge\ \ (b-a)|(m\ mod\ a) $​

C

Description

​ 给你一个图,保证每个点最多属于一个简单环,每个点度数最多为 \(3\) ,求这个图有多少“眼镜图形”。

​ 其中“眼镜图形”,定义为三元组 \((x,y,S)\) ,其中 \(x\)\(y\) 表示图上的两个点,\(S\) 表示一条 \(x\)\(y\) 的简单路径,而且必须满足:

​ 1 . \(x\)​​ 和 \(y\)​​​ 分别在两个不同的简单环上

​ 2 . \(x\) 所在的简单环与路径 \(S\) 的所有交点仅有 \(x\)\(y\) 所在的简单环与路径S的所有交点仅有 \(y\)
\((x,y,s)\)\((y,x,S)\) 算同一个眼镜。

​ 保证图是联通的

Input

​ 第一行两个数 \(n,m\)

​ 之后 \(m\)​ 行,每行两个数 \(x,y\)​ 表示 \(x\)\(y\) 之间有一条边。

Output

​ 输出一个数,表示眼镜的个数对 \(19260817\) 取膜的结果

Example

input 1
11 12
1 2
2 3
3 4
4 5
5 1
4 6
6 7
7 8
8 9
9 10
10 11
11 7
output 1
1
input 2
14 16
1 2
2 3
3 4
4 1
3 5
5 6
6 7
7 8
8 9
9 6
9 13
13 14
13 10
10 11
11 12
12 10
output 2
4

Hint

​ 满足 \(1 \leq n \leq 10^6\ ,\ 1 \leq m \leq 2*10^6\)

Solution

​ 对于每个简单环,删去环上的边,新建一个虚点对环上所有点连边,于是原图变为一棵树。

​ 于是原图的每一个“眼镜”都对应到树上的一对虚点 \(u,v\)​​ ,记 \(cnt\) 表示树上 \(u \rightarrow v\)​ 经过的虚点个数,则该对虚点的贡献为 \(2^{cnt-2}\)

​ 直接对新图DFS求解。

D

Description

​ 给出三个长度 \(n\)​ 的正整数序列 \(A,B,C\)​ 。
​ 定义 \(f(X,l,r)\)​ 为在序列 \(X\)​ 中,区间 \([l,r]\)​ 的最大值减去区间 \([l,r]\)​ 的最小值的差。
​ 定义一个区间 \([l,r]\)​ 的权值为 \(f(A,l,r) * f(B,l,r) * f(C,l,r)\)​。
​ 求对于所有 \(1 \leq l \leq r \leq n\)​ ,区间 \([l,r]\)​ 的权值之和,由于答案可能比较大,所以输出答案对 \(2^{32}\)​ 取模的结果

Input

​ 第一行一个整数 \(n\)
​ 之后三行,每行 \(n\) 个正整数,分别表示 \(A,B,C\) 三个序列。

Output

​ 一行一个数表示答案。

Example

input
5
1 3 5 5 5
2 3 2 1 2
3 5 5 3 5
output
60

Hint

​ 满足 \(1 \leq n \leq 10^5\ ,\ 1 \leq A_i,B_i,C_i \leq 10^9\)

Solution

​ 记 \(M(X,l,r)=max_{i=l}^{r}\left\{X_i\right\}\ ,\ N(X,l,r)=min_{i=l}^{r}\left\{X_i\right\}\ ,\ (-X)=\left\{-X_i|i \in [1,n]\right\}\ ,\ (+X)=X\)​​

​ 那么 \(f(X,l,r)=M(X,l,r)-N(X,l,r)=M(X,l,r)+M(-X,l,r)\)

​ 记 \(F(l,r)=f(A,l,r) * f(B,l,r) * f(C,l,r)\)

​ 于是:

\[\ \begin{cases} Ans&=\sum_{l=1}^{n}{\sum_{r=l}^{n}{F(l,r)}}\\ F(l,r)&=\prod_{X=A,B,C}{(M(X,l,r)+M(-X,l,r))}\\ &=\sum_{X_1=\pm A}{\sum_{X_2=\pm B}{\sum_{X_3=\pm C}{\prod_{X=X_1,X_2,X_3}{M(X,l,r)}}}} \end{cases}\\ \Longrightarrow Ans=\sum_{l=1}^{n}{\sum_{r=l}^{n}\ {\sum_{X_1=\pm A}\ {\sum_{X_2=\pm B}\ \ {\sum_{X_3=\pm C}\ {\prod_{X=X_1,X_2,X_3}{M(X,l,r)}}}}}}\\ =\sum_{X_1=\pm A}\ {\sum_{X_2=\pm B}\ {\sum_{X_3=\pm C}\ {\sum_{l=1}^{n}{\sum_{r=l}^{n}\ \ {\prod_{X=X_1,X_2,X_3}{M(X,l,r)}}}}}} \]

​ 现在只需考虑如何计算 \(\sum_{l=1}^{n}{\sum_{r=l}^{n}\ \ {\prod_{X=X_1,X_2,X_3}{M(X,l,r)}}}\)

​ 不妨假设 \(X_1=A\ ,\ X_2=B\ ,\ X_3=C\) 其它情况同此处理

​ 考虑线段树分治,于是问题转化为求 \(\sum_{l=L}^{mid}{\sum_{r=mid+1}^{R}\ \ {\prod_{X=A,B,C}{M(X,l,r)}}}\)

​ 可以枚举 \(l\)\(\sum_{r=mid+1}^{R}{\prod_{X=A,B,C}{M(X,l,r)}}\)

​ 显然 \(M(X,l,r)=max\left\{M(X,l,mid)\ ,\ M(X,mid+1,r)\right\}\)

​ 对于每个 \(l\) ,有确定的 \(p_{_A},st\ \ p_{_A}=max\left\{p \in [mid+1,R]\ |\ M(A,mid+1,p) \leq M(A,l,mid)\right\}\) 同理可求出确定的 \(p_{_B}\ ,\ p_{_C}\) (这里不妨假设 \(p_{_A} \leq p_{_B} \leq p_{_C}\) 其它情况类似计算),于是

\[\begin{equation} \begin{aligned} &\sum_{r=mid+1}^{R}{\prod_{X=A,B,C}{M(X,l,r)}}\ \\ =&\ \sum_{r=mid+1}^{p_{_A}}{(\prod_{X=A,B,C}{M(X,l,mid)})}\\ +&\sum_{r=p_{_A}+1}^{p_{_B}}{(M(A,mid+1,r)*M(B,l,mid)*M(C,l,mid))}\\ +&\sum_{r=p_{_A}+1}^{p_{_B}}{(M(A,mid+1,r)*M(B,mid+1,r)*M(C,l,mid))}\\ +&\sum_{r=p_{_A}+1}^{p_{_B}}{(M(A,mid+1,r)*M(B,mid+1,r)*M(C,mid+1,r))}\\ =&\ \ (p_{_A}-mid)*M(A,l,mid)*M(B,l,mid)*M(C,l,mid)\\ +&\big(\sum_{r=p_{_A}+1}^{p_{_B}}{M(A,mid+1,r)}\ \big)\ *M(B,l,mid)*M(C,l,mid)\\ +&\Big(\sum_{r=p_{_B}+1}^{p_{_C}}{\big(\ M(A,mid+1,r)*M(B,mid+1,r)\ \big)}\ \Big)\ *M(C,l,mid)\\ +& \sum_{r=p_{_C}+1}^{R}{\big(\ M(A,mid+1,r)*M(B,mid+1,r)*M(C,mid+1,r)\ \big)} \end{aligned}\notag\ \end{equation} \]

​ 利用前缀和优化可\(O(1)\)​​​​计算上式,\(p_{{_A} {_/} {_B} {_/} {_C}}\)​ 随着 \(l\) 单调变化而单调变化,计算复杂度均摊\(O(1)\)​,由于线段树分治,总复杂度\(O(n\,logn)\)​​​

Code
#define Max(a,b) ((a)<(b)?(a)=(b):0)
int n,A[100005],B[100005],C[100005];
uint Ans;
//以下是前缀和的预处理
uint Sa[100005],Sb[100005],Sc[100005],Sab[100005],Sbc[100005],Sca[100005],Sabc[100005];
inline void Prep1(uint *F,int *Q,int l,int r){
	F[l-1]=0;int Cur=Q[l];for(int i=l;i<=r;i++){
		if(Cur<Q[i])Cur=Q[i];F[i]=F[i-1];F[i]+=Cur;
	}
}
inline void Prep2(uint *F,int *Q1,int *Q2,int l,int r){
	F[l-1]=0;int cur1=Q1[l],cur2=Q2[l];
	for(int i=l;i<=r;i++){
		if(cur1<Q1[i])cur1=Q1[i];if(cur2<Q2[i])cur2=Q2[i];
		F[i]=F[i-1];F[i]+=1u*cur1*cur2;
	}
}
inline void Prep3(uint *F,int *Q1,int *Q2,int *Q3,int l,int r){
	F[l-1]=0;int cur1=Q1[l],cur2=Q2[l],cur3=Q3[l];
	for(int i=l;i<=r;i++){
		if(cur1<Q1[i])cur1=Q1[i];if(cur2<Q2[i])cur2=Q2[i];if(cur3<Q3[i])cur3=Q3[i];
		F[i]=F[i-1];F[i]+=1u*cur1*cur2*cur3;
	}
}
//以上是前缀和的预处理

inline void Calc(int Q1,int Q2,int Q3,uint *F1,uint *F2,uint *F3,int t1,int t2,int t3,int mid,int r){
	Ans+=1u*Q1*Q2*Q3*(t1-mid);Ans+=1u*Q2*Q3*(F1[t2]-F1[t1]);Ans+=1u*Q3*(F2[t3]-F2[t2]);Ans+=F3[r]-F3[t3];
}//计算贡献
void Solve(int l,int r){
	if(l==r){Ans+=1u*A[r]*B[r]*C[r];return;};
	int mid=(l+r)>>1;
    Solve(l,mid);Solve(mid+1,r);//线段树分治
	uint AA=Ans;
	Prep1(Sa,A,mid+1,r);Prep1(Sb,B,mid+1,r);Prep1(Sc,C,mid+1,r);
	Prep2(Sab,A,B,mid+1,r);Prep2(Sbc,B,C,mid+1,r);Prep2(Sca,C,A,mid+1,r);
	Prep3(Sabc,A,B,C,mid+1,r);//预处理
    int toa=mid,tob=mid,toc=mid,ma=A[mid],mb=B[mid],mc=C[mid];
    //toa:pA  tob:pB  toc:pC  ma:M(A,l,mid)  mb:M(B,l,mid)  mc:M(C,l,mid)
	for(int i=mid;i>=l;i--){
		Max(ma,A[i]);Max(mb,B[i]);Max(mc,C[i]);
		while(toa<r&&A[toa+1]<=A[i])toa++;
		while(tob<r&&B[tob+1]<=B[i])tob++;
		while(toc<r&&C[toc+1]<=C[i])toc++;
		if(toa<=tob&&tob<=toc)Calc(ma,mb,mc,Sa,Sab,Sabc,toa,tob,toc,mid,r);//abc
		else if(toa<=tob&&toa<=toc)Calc(ma,mc,mb,Sa,Sca,Sabc,toa,toc,tob,mid,r);//acb
		else if(toa<=tob)Calc(mc,ma,mb,Sc,Sca,Sabc,toc,toa,tob,mid,r);//cab
		else if(toa<=toc)Calc(mb,ma,mc,Sb,Sab,Sabc,tob,toa,toc,mid,r);//bac
		else if(tob<=toc)Calc(mb,mc,ma,Sb,Sbc,Sabc,tob,toc,toa,mid,r);//bca
		else Calc(mc,mb,ma,Sc,Sbc,Sabc,toc,tob,toa,mid,r);//cba
	}
	return;
}
int main(){
	Read(n);
	for(int i=1;i<=n;i++)Read(A[i]);
	for(int i=1;i<=n;i++)Read(B[i]);
	for(int i=1;i<=n;i++)Read(C[i]);
	Solve(1,n);//a b c
	for(int i=1;i<=n;i++)A[i]=-A[i];Solve(1,n);//-a b c
	for(int i=1;i<=n;i++)B[i]=-B[i];Solve(1,n);//-a -b c
	for(int i=1;i<=n;i++)C[i]=-C[i];Solve(1,n);//-a -b -c
	for(int i=1;i<=n;i++)A[i]=-A[i];Solve(1,n);//a -b -c
	for(int i=1;i<=n;i++)B[i]=-B[i];Solve(1,n);//a b -c
	for(int i=1;i<=n;i++)A[i]=-A[i];Solve(1,n);//-a b -c
	for(int i=1;i<=n;i++)A[i]=-A[i],B[i]=-B[i],C[i]=-C[i];Solve(1,n);//a -b c
	cout<<Ans<<'\n';
	return 0;
} 
posted @ 2021-07-25 20:55  沼中蒻杨  阅读(70)  评论(0编辑  收藏  举报