Codeforces 788 (Div. 1)
Posted blogofchc1234567890
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 788 (Div. 1)相关的知识,希望对你有一定的参考价值。
788 A
题意
给你一个长度为 (n) 的序列 (a) ,定义函数
其中 (1le l<rle n)
求对于所有可能的 (l,r,f(l,r)) 的最大值
((2le nle 100000))
Examples
Input
5
1 4 2 3 1
Output
3
Input
4
1 5 4 7
Output
6
解
设 (dp[i][0]) 为未计算当前节点能达到的最大值, (dp[i][1]) 为计算当前节点能达到的最大值.
每枚举一个 (i) ,(ans) 都取一遍 (max)
转移方程:
dp[i][0]=max(dp[i-1][1]-s[i],0);
dp[i][1]=max(dp[i-1][0]+s[i],s[i]);
ans=max(ans,max(dp[i][0],dp[i][1]));
788 B
题意
给你一张图,有自环,无重边,找出一条路径,使得它经过所有的边,且经过这些边的其中两条恰好 (1) 次,经过其他边恰好 (2) 次。
求出所有满足条件的路径数量。
((1le n,mle 10^6))
Examples
Input
5 4
1 2
1 3
1 4
1 5
Output
6
Input
5 3
1 2
2 3
4 5
Output
0
Input
2 2
1 1
1 2
Output
1
解
设对于一对边,如果存在一条合法路径,使这条路径经过着两条边恰好 (1) 次,那么我们称这一对边是合法的。
经过一番波折,我们推出:两两非自环边搭配必定合法;自环与任意一条边(可以是自环,也可以不是)搭配都合法。
最后累计。
788 C
题意
有 (k) 瓶不同浓度的可乐,每瓶1000mL,现在要求配一瓶浓度为 (n) mL/1000mL 的可乐,问最少需要几瓶。((0?≤?n?≤?1000, 1?≤?k?≤?10^6))
Examples
Input
400 4
100 300 450 500
Output
2
Input
50 2
100 25
Output
3
解
将每瓶饮料的浓度减去 (n)
题目可以转换为求一条最短路,这条最短路上的权值之和为 (0) ,且长度最小
我们发现,合法的浓度不会超过 (2000) 种
于是用dijkstra搞一下就好了
后来发现其实只需要一个bfs!!
788 D
题意
交互题
平面上有 (n) 条直线,与坐标轴平行。现在,你有至多 (3×10^5) 次机会询问,每次询问形如 (0;x;y) ,系统将返回与这个点距离最近的直线到它的距离。
直到已知所有直线的解析式,要求输出。
((1le nle 2×10^4,直线坐标,询问坐标le 10^8))
Example
Input
1
1
3
2
Output
0 1 2
0 -2 -2
0 5 6
0 -2 2
1 1 2
2
0 -3
解
从点 ((-10^8,-10^8)) 沿直线 (y=x) 向上询问
设询问结果为ret
如果ret==0,那么将当前位置向右上平移1距离
否则将当前位置向右上平移ret距离
这样的话会 ( ext{TLE}) 一个点,需要加一个剪枝
就是如果当前搜到一个点ret!=0,且这个点向上100距离搜到的点ret也!=0,那么直接向上跳100距离
好了
788 E
题意
有 (n) 个士兵,要选5个参加比赛
选的5个人合法的条件是:设这5个人的下标为 (i,j,k,l,p) ,满足 (1le i<j<k<l<ple n) 且 (a_ile a_j = a_k = a_l ≥ a_p) 。
现在有 (m) 次操作,每次操作规定某一个士兵不能作为 (j,k,l) 参加比赛或者能作为...参加比赛
对于每次操作,需要输出操作后选择5个人的方案数
膜 (10^9+7)
((1le n,mle 10^5,1le a_ile 10^9))
Examples
Input
6
1 1 1 1 1 1
2
1 3
2 3
Output
1
6
Input
8
3 4 4 2 4 5 4 1
3
1 5
2 5
1 2
Output
1
6
2
解
第一步:树状数组+离散化,维护 (pre[i],nxt[i]) ,分别表示 (a[i]) 前面的数中 (le a[i]) 的有多少个, (a[i]) 后面的数中 (le a[i]) 的有多少个。
第二步:线段树,对每个离散化的 (a[i]) 的值开一个线段树(动态开点),每个节点维护 (6) 个值: (A,B,C,AB,BC,ABC) ,表示当前节点所表示区间选出 j,k,l,j和k,k和l,j、k和l 的方案数。
具体操作:
先预处理出未进行任何操作时的答案。
叶子节点初始值:
t[p].A=pre[l];
t[p].B=1;
t[p].C=nxt[r];
t[p].AB=t[p].BC=t[p].ABC=0;
对于每次操作,对线段树进行单点修改。
对于每次操作后的询问,查询区间 ([1,n]) 。
Code
#include<bits/stdc++.h>
#define maxn 200003
#define mod 1000000007
using namespace std;
int Plus(long long x,long long y){return (x+=y)>=mod?x%mod:x;}
int Minus(long long x,long long y){return (x+=mod-y)>=mod?x%mod:x;}
int mul(long long x,long long y){return (x*=y)>=mod?x%mod:x;}
int n,a[maxn],mp[maxn],cntmp,pre[maxn],nxt[maxn];
namespace BIT{
int t[maxn];
void clear(){
for(int i=1;i<=n;i++)t[i]=0;
}
void add(int pos,int k){
while(pos<=n){
t[pos]+=k;
pos+=pos&-pos;
}
}
int query(int pos){
int ret=0;
while(pos){
ret+=t[pos];
pos-=pos&-pos;
}
return ret;
}
}
namespace SEG{
struct node{
int _2,_3,_4,_23,_34,_234,son[2];
node():_2(0),_3(0),_4(0),_23(0),_34(0),_234(0){son[0]=son[1]=0;}
}t[maxn*20];
int cnt,root[maxn];
void pushup(int p){
int son0=t[p].son[0],son1=t[p].son[1];
t[p]._2=Plus(t[son0]._2,t[son1]._2);
t[p]._3=Plus(t[son0]._3,t[son1]._3);
t[p]._4=Plus(t[son0]._4,t[son1]._4);
t[p]._23=Plus(mul(t[son0]._2,t[son1]._3),Plus(t[son0]._23,t[son1]._23));
t[p]._34=Plus(mul(t[son0]._3,t[son1]._4),Plus(t[son0]._34,t[son1]._34));
t[p]._234=Plus(Plus(Plus(mul(t[son0]._2,t[son1]._34),mul(t[son0]._23,t[son1]._4)),t[son0]._234),t[son1]._234);
}
void change(int& p,int l,int r,int pos,bool k){
if(p==0)p=++cnt;
if(l==r){
t[p]._2=k*pre[pos];
t[p]._3=k;
t[p]._4=k*nxt[pos];
return;
}
int mid=(l+r)>>1;
if(pos<=mid)change(t[p].son[0],l,mid,pos,k);
else change(t[p].son[1],mid+1,r,pos,k);
pushup(p);
}
int query(int p){
return t[p]._234;
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",a+i);
mp[++cntmp]=a[i];
}
sort(mp+1,mp+cntmp+1);
cntmp=unique(mp+1,mp+cntmp+1)-mp-1;
for(int i=1;i<=n;i++)a[i]=lower_bound(mp+1,mp+cntmp+1,a[i])-mp;
for(int i=1;i<=n;i++){
pre[i]=BIT::query(a[i]);
BIT::add(a[i],1);
}
BIT::clear();
for(int i=n;i>=1;i--){
nxt[i]=BIT::query(a[i]);
BIT::add(a[i],1);
}
int ans=0;
for(int i=1;i<=n;i++){
ans=Minus(ans,SEG::query(SEG::root[a[i]]));
SEG::change(SEG::root[a[i]],1,n,i,1);
ans=Plus(ans,SEG::query(SEG::root[a[i]]));
}
int Q;
scanf("%d",&Q);
while(Q--){
int mo,x;
scanf("%d%d",&mo,&x);
ans=Minus(ans,SEG::query(SEG::root[a[x]]));
if(mo==1)SEG::change(SEG::root[a[x]],1,n,x,0);
else SEG::change(SEG::root[a[x]],1,n,x,1);
ans=Plus(ans,SEG::query(SEG::root[a[x]]));
printf("%d
",ans);
}
return 0;
}
以上是关于Codeforces 788 (Div. 1)的主要内容,如果未能解决你的问题,请参考以下文章
CodeForces 788B--Weird journey
Codeforces 788C The Great Mixing(背包问题建模+bitset优化或BFS)