• 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("");
    	}
    }
    
  • 相关阅读:
    javaXML文件的写入之DOM和DOM4J
    javaXML文件解析之DOM4J实操
    java解析XML文件四种方法之引入源文件
    java文件传输之文件编码和File类的使用
    java中Collections.sort()方法实现集合排序
    java集合的contains(obj)方法的实现
    java集合及其方法
    java基本数据类型及其包装类
    java类的种类
    java类定义、变量类型、构造函数
  • 原文地址:https://www.cnblogs.com/dixiao/p/15630917.html
Copyright © 2020-2023  润新知