CF1495F Squares

曾经以为自己只是不会做脑子题。
现在发现自己什么都不会。

一台机,一杯水,一个*3300写一晚上

被套路题教育了。

经典结论:在右侧最近的具有偏序关系的这类点对\((i,p_i)\)
\(\max_{i \leq j \leq p_i}p_j \leq p_i\)

那么我们发现如果我们要向右走的话如果没有点集要求,那么就是

\(dis(1,n + 1)\)

加入一个点,或删除一个点,其等价于加入一个强制经过的点,那么我们只要能求出\(dis(x,y)\)则能很快的维护出答案。

考虑如何求出\(dis(x,y)\)

我们可以按点对\((i,p_i)\) 建出一颗 \(tree\),那么我们可以一直倍增调整到\([now,y]\),\(y\)不是\(now\)的祖先。

我们可以在树上处理出两种操作向上的最少需要的权值。

那么此时我们知道\(now > y\) 我们无法在树上跳过去。

那么我们只能强制采用A操作一次。然后我们发现此时后面的操作为固定操作。

此固定操作即为简化爬树过程后实际上是在原序列的单调不上升序列上跳跃,预处理即可

我们可以求出\(ldis_u\)表示从\(1 \to u\) 的按固定操作的权值。

那么考虑更新\(ldis_u\),那么一定是找到第一个没法操作的地方,然后加一,此时我们发现这个没法操作的地方一直往上跳就显然可以操作到\(u\)

所以\(dis(x,y)\) 的查询即我们先一直在树上跳,然后做一次A操作,然后一直在单调不上升序列上跳跃。

可以具体看看代码。

关键性质是理解

经典结论:在右侧最近的具有偏序关系的这类点对\((i,p_i)\)
\(\max_{i \leq j \leq p_i}p_j \leq p_i\)

本代码\(TLE on 11\),查了一晚上也没查出来为什么,只好暂时放弃。

#pragma GCC diagnostic error "-std=c++11"
#pragma GCC target("avx")
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")

#include<bits/stdc++.h>
#define ll long long 
#define N 300005

int L[N],R[N],fa[N][25];

ll a[N],b[N],p[N];

int n,q;

ll ldis[N],val[N][25];

int stk[N],top;

std::vector<int>G[N];

int cnt = 0;

inline void dfs(int u){
	L[u] = ++cnt;
	for(int i = 0;i < G[u].size();++i){
		int v = G[u][i];
		fa[v][0] = u;
		for(int i = 1;i <= 20;i ++ )
		fa[v][i] = fa[fa[v][i - 1]][i - 1];
		dfs(v);
	}
	R[u] = cnt;	
}

inline bool FA(int a,int b){
	return L[a] <= L[b] && L[b] <= R[a];
}

inline ll dis(int a,int b){
	ll res = 0;
	for(int i = 20;i >= 0;--i)
	if(fa[a][i] && fa[a][i] <= b)
	res += val[a][i],a = fa[a][i];
	return res + ldis[b] - ldis[a];
}

std::set<int>S;

int vis[N];

ll ans = 0;

inline void del(int x){
	std::set<int>::iterator it = std::lower_bound(S.begin(),S.end(),x);
	int las = * --it;
	++it;
	int nex = * ++it;
	if(S.find(x) == S.end())
	puts("-1");
	else
	S.erase(x);
	vis[x] = 0;
	ans = ans - dis(las,x) - dis(x,nex) + dis(las,nex); 
}
char IO;
ll read(int res=0){
	bool f=0;
	while(IO=getchar(),IO<48||IO>57)
		f|=IO=='-';
	do res=(res<<1)+(res<<3)+(IO^48);
	while(IO=getchar(),isdigit(IO));
	return f?-res:res;
}

inline void add(int x){
	std::set<int>::iterator it = std::lower_bound(S.begin(),S.end(),x);
	int las = * --it;
	int nex = * ++it;
//	std::cout<<las<<" "<<nex<<" "<<dis(las,x)<<" "<<dis(x,nex)<<std::endl;
	if(S.find(x) != S.end())
	puts("-1");
	else
	S.insert(x);
	vis[x] = 1;
	ans = ans + dis(las,x) + dis(x,nex) - dis(las,nex); 	
}

template<typename T> inline void write(T x)
{
   	short st[30],tp=0;
	if(x<0) putchar('-'),x=-x;
	do st[++tp]=x%10,x/=10; while(x);
	while(tp) putchar('0'|st[tp--]);
}

signed main(){
	n = read(),q = read();
	p[n + 1] = 1e10;
	for(int i = 1;i <= n;++i)
	p[i] = read();
	for(int i = 1;i <= n;++i)
	a[i] = read();
	for(int i = 1;i <= n;++i)
	b[i] = read();
	stk[++top] = n + 1;
	for(int i = n;i >= 1;--i){
		while(top && p[stk[top]] <= p[i])
		top -- ;
		G[stk[top]].push_back(i);
		stk[++top] = i;
	}
	dfs(n + 1);
	for(int i = n;i >= 1;--i){
//		std::cout<<L[i]<<" "<<R[i]<<std::endl;
		int t = i + 1;
		ll res = a[i];
		for(int j = 20;j >= 0;--j)
		if(FA(fa[i][0],fa[t][j]) && fa[i][0] && fa[t][j])
		res += val[t][j],t = fa[t][j];
		val[i][0] = std::min(res,b[i]);
		for(int j = 1;j <= 20;++j)
		val[i][j] = val[i][j - 1] + val[fa[i][j - 1]][j - 1];
//		for(int j = 0;j <= 20;++j)
//		std::cout<<val[i][j]<<" ";
//		puts("");
	}
	top = 0;
	for(int i = 1;i <= n;++i){
		while(top && p[stk[top]] < p[i])
		top -- ;
		if(top)ldis[i] = ldis[stk[top]] + dis(stk[top] + 1,i) + a[stk[top]];
		stk[++top] = i;
	}
	S.insert(1);
	S.insert(n + 1);
	ans = dis(1,n + 1);
	while(q -- ){
		int x;
		x = read();
		if(x != 1){
			if(vis[x])
			del(x);
			else
			add(x);
		}
		write(ans);
		puts("");
	}
}
posted @ 2021-12-01 21:48  fhq_treap  阅读(25)  评论(0编辑  收藏  举报