复习与回顾: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)\)
于是:
现在只需考虑如何计算 \(\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}\) 其它情况类似计算),于是
利用前缀和优化可\(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;
}
本文来自博客园,作者:蒻杨,转载请注明原文链接:https://www.cnblogs.com/weed-yang/