$$ \newcommand{\seq}[2]{{#1}_{1},{#1}_{2},\cdots,{#1}_{#2}} \newcommand{\num}[1]{1,2,\cdots,#1} \newcommand{\stra}[2]{\begin{bmatrix}#1 \\ #2\end{bmatrix}} \newcommand{\strb}[2]{\begin{Bmatrix}#1 \\ #2\end{Bmatrix}} \newcommand{\dw}[1]{\underline{#1}} \newcommand{\up}[1]{\overline{#1}} $$

Codeforces 788 (Div. 1)

788 A

题意

给你一个长度为 \(n\) 的序列 \(a\) ,定义函数

其中 \(1\le l<r\le n\)
求对于所有可能的 \(l,r,f(l,r)\) 的最大值
\((2\le n\le 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\) 次。
求出所有满足条件的路径数量。
\((1\le n,m\le 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\) ,系统将返回与这个点距离最近的直线到它的距离。
直到已知所有直线的解析式,要求输出。
\((1\le n\le 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距离
这样的话会 \(\text{TLE}\) 一个点,需要加一个剪枝
就是如果当前搜到一个点ret!=0,且这个点向上100距离搜到的点ret也!=0,那么直接向上跳100距离
好了

788 E

题意

\(n\) 个士兵,要选5个参加比赛
选的5个人合法的条件是:设这5个人的下标为 \(i,j,k,l,p\) ,满足 \(1\le i<j<k<l<p\le n\)\(a_i\le a_j = a_k = a_l ≥ a_p\)
现在有 \(m\) 次操作,每次操作规定某一个士兵不能作为 \(j,k,l\) 参加比赛或者能作为...参加比赛
对于每次操作,需要输出操作后选择5个人的方案数
\(10^9+7\)
\((1\le n,m\le 10^5,1\le a_i\le 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\n",ans);
	}
	return 0;
}

posted @ 2019-02-21 21:01  chc_1234567890  阅读(244)  评论(0编辑  收藏  举报