题解:P16352 「Gensokyo OI Round 1」雨后长虹
前言
乱炖题吧。
思路
树
首先我们考虑树的情况,我们发现对于两个点
具体来说,对于操作
对于他说的不能选择点集中的点我们只需要在每次查询前先将每一个点的最小值改为极大值,和改为
图
考虑将树的做法类推到图上,我们发现对于图上的
代码
简直是史。
#include <bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include <ext/rope>
using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define rep(i,x,y) for(register int i=x;i<=y;i++)
#define rep1(i,x,y) for(register int i=x;i>=y;--i)
#define int long long
#define fire signed
#define il inline
template<class T> il void print(T x) {
if(x<0) printf("-"),x=-x;
if (x > 9) print(x / 10);
putchar(x % 10 + '0');
}
template<class T> il void in(T &x) {
x = 0; char ch = getchar();
int f = 1;
while (ch < '0' || ch > '9') {if(ch=='-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar(); }
x *= f;
}
int T=1;
const int N=2e5+10;
int a[N];
int n,m;
int dfn[N],low[N];
stack<int>s;
vector<int>v[N];
vector<int>ve[N];
int idx,tot,rt[N],ss[N];
void tarjan(int x,int fr) {
dfn[x]=low[x]=++tot;
ss[fr]++;
s.push(x);
rt[x]=fr;
for(auto to:v[x]) {
if(!dfn[to]) {
tarjan(to,fr);
low[x]=min(low[x],low[to]);
if(low[to]==dfn[x]) {
idx++;
int p;
do{
p=s.top();
s.pop();
ve[idx].pb(p);
ve[p].pb(idx);
}while(p!=to);
ve[idx].pb(x);
ve[x].pb(idx);
}
}else low[x]=min(low[x],dfn[to]);
}
}
struct node{
int l,r;
int mn,sum;
}tr[N<<2];
void up(int x) {
tr[x].mn=min(tr[x<<1].mn,tr[x<<1|1].mn);
tr[x].sum=tr[x<<1].sum+tr[x<<1|1].sum;
}
int siz[N],mx[N];
int fat[N],dep[N],val[N];
void dfs(int x,int fa) {
fat[x]=fa;
dep[x]=dep[fa]+1;
siz[x]=1;
for(auto to:ve[x]) {
if(to==fa) continue;
dfs(to,x);
siz[x]+=siz[to];
if(siz[to]>siz[mx[x]]) mx[x]=to;
}
}
int top[N],df[N],dd,v1[N],a1[N];
void dfs1(int x,int h) {
top[x]=h;
df[x]=++dd;
val[dd]=a[x];
v1[dd]=a1[x];
if(!mx[x]) return;
dfs1(mx[x],h);
for(auto to:ve[x]) {
if(!df[to]) dfs1(to,to);
}
}
const int inf=1e18;
void build(int u,int l,int r) {
tr[u]={l,r,inf,0};
if(l==r) {
tr[u].mn=val[l];
tr[u].sum=v1[l];
return;
}
int mid=l+r>>1;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
up(u);
}
void modify(int u,int x,int k,int k1) {
if(tr[u].l==tr[u].r) {
tr[u].mn=k1,tr[u].sum=k;
return;
}
int mid=tr[u].l+tr[u].r>>1;
if(mid>=x) modify(u<<1,x,k,k1);
else modify(u<<1|1,x,k,k1);
up(u);
}
int Ans(int u,int l,int r) {
if(l>r) return false;
if(tr[u].l>=l&&tr[u].r<=r) return tr[u].sum;
int mid=tr[u].l+tr[u].r>>1,res=0;
if(mid>=l) res=Ans(u<<1,l,r);
if(mid<r) res+=Ans(u<<1|1,l,r);
return res;
}
int Ans1(int u,int l,int r) {
if(l>r) return inf;
if(tr[u].l>=l&&tr[u].r<=r) {
return tr[u].mn;
}
int mid=tr[u].l+tr[u].r>>1,res=inf;
if(mid>=l) res=Ans1(u<<1,l,r);
if(mid<r) res=min(res,Ans1(u<<1|1,l,r));
return res;
}
bool cmp(int x,int y) {
return df[x]<df[y];
}
int f[N][20];
void init() {
rep(j,1,19) rep(i,1,idx) f[i][j]=f[f[i][j-1]][j-1];
}
int lca(int x,int y) {
if(dep[x]>dep[y]) swap(x,y);
rep1(i,19,0) if(dep[f[y][i]]>=dep[x]) y=f[y][i];
if(x==y) return x;
rep1(i,19,0) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
return f[x][0];
}
int get(int x,int y) {
int res=inf;
while(top[x]!=top[y]) {
if(dep[top[x]]<dep[top[y]]) swap(x,y);
res=min(res,Ans1(1,df[top[x]],df[x]));
x=fat[top[x]];
}
if(df[x]>df[y]) swap(x,y);
res=min(res,Ans1(1,df[x],df[y]));
return res;
}
int get1(int x,int y) {
int res=0;
while(top[x]!=top[y]) {
if(dep[top[x]]<dep[top[y]]) swap(x,y);
res+=Ans(1,df[top[x]],df[x]);
x=fat[top[x]];
}
if(df[x]>df[y]) swap(x,y);
res+=Ans(1,df[x],df[y]);
return res;
}
void solve() {
in(n),in(m);
idx=n;
rep(i,1,n) in(a[i]),a1[i]=a[i];
rep(i,1,m) {
int x,y;
in(x),in(y);
v[x].pb(y);
v[y].pb(x);
}
rep(i,1,n) if(!dfn[i]) tarjan(i,i);
rep(i,n+1,idx) a[i]=1e18,a1[i]=0;
dfs(1,0);
dfs1(1,1);
build(1,1,dd);
int q;
in(q);
rep(i,1,dd) f[i][0]=fat[i];
init();
while(q--) {
int opt;
in(opt);
if(opt==1) {
int qc;
in(qc);
vector<int>arr;
vector<array<int,2>>vk;
rep(i,1,qc) {
int x;
in(x);
arr.pb(x);
vk.pb({x,a[x]});
modify(1,df[x],0,inf);
}
sort(arr.begin(),arr.end(),cmp);
int len=arr.size(),res=1e18;
rep(i,0,len-2) {
res=min(res,get(arr[i],arr[i+1]));
}
if(res>=inf) puts("-1");
else printf("%lld\n",res);
for(auto to:vk) modify(1,df[to[0]],to[1],to[1]);
}else if(opt==2) {
int qc;
in(qc);
vector<int>arr;
vector<array<int,2>>vk;
rep(i,1,qc) {
int x;
in(x);
arr.pb(x);
vk.pb({x,a[x]});
modify(1,df[x],0,inf);
}
sort(arr.begin(),arr.end(),cmp);
arr.erase(unique(arr.begin(),arr.end()),arr.end());
int len=arr.size(),res=0;
int tt=arr[0];
for(auto to:arr) res+=get1(1,to),tt=lca(tt,to);
arr.pb(arr[0]);
rep(i,0,len-1) {
int lc=lca(arr[i],arr[i+1]);
res-=get1(1,lc);
}
res+=Ans(1,df[tt],df[tt]);
if(!res) puts("-1");
else printf("%lld\n",res);
for(auto to:vk) modify(1,df[to[0]],to[1],to[1]);
}else {
int x,k;
in(x),in(k);
a[x]=k;
modify(1,df[x],k,k);
}
}
}
fire main() {
while(T--) {
solve();
}
return false;
}