【P2194 HXY燒情侶】題解
阿新 • • 發佈:2021-11-27
不動身的話就永遠無法追尋,哪怕是休息也不會就此停下。
,\(y\)不是\(now\)的祖先。
曾經以為自己只是不會做腦子題。
現在發現自己什麼都不會。
一臺機,一杯水,一個*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]\)
我們可以在樹上處理出兩種操作向上的最少需要的權值。
那麼此時我們知道\(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(""); } }