loj #2049. 「HNOI2016」网络 ( JSOIP2022练习赛1 t2 )
题面太长
操作应当是按照时间插入,此时一个思路是考虑线段树分治,但是发现并不需要 .
考虑加入一个交互会发生什么,除了当前路径上的点最大值会取 \(\max\) ,因为当前路径在树链剖分上是 \(\log n\) 个区间,那么,除去这个路径的部分也是 \(\log n\) 个区间 . 依旧可以树链剖分 + 线段树 .
此时,这个操作是需要撤销的,所以考虑维护一个 \(\rm{multiset}\) 来支持撤销的操作 . 此时的时间复杂度就是 \(O(n\log^3n)\) . 在 loj 开了 Ofast 需要跑接近 3s,显然不太好 .
**此时考虑将 \(\rm{multiset}\) 换成 \(\rm{priority\_queue}\) 则会快很多,考虑维护两个栈 \(q_1\) 和 \(q_2\),其中 \(q_1\) 维护当前出现过,还没有被删除的值 , \(q_2\) 维护删除的值 . 当 \(q_1.top()=q_2.top()\) 的时候,需要弹出 \(q_1.top()\) **. 具体实现 :
class node{
public:
priority_queueq1,q2;
inline void ins(int val){q1.push(val);}
inline void era(int val){q2.push(val);}
inline int top(){
while(!q2.empty()&&q2.top()==q1.top())q1.pop(),q2.pop();
return q1.empty()?-1:q1.top();
}
};
将操作改成用两个 \(\rm{pq}\) 维护就好很多 ,每个点跑了 300ms 不到,是 10 倍的差距,同时在内存上也显示出了优势,从接近 400MB 变为了 75MB- .
时间复杂度 : \(O(n\log^3 n)\)
空间复杂度 : \(O(n\log n)\)
code
//#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline") //Optimization flags
//#pragma GCC option("arch=native","tune=native","no-zero-upper") //Enable AVX
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2")
#include
using namespace std;
char in[100005];
int iiter=0,llen=0;
inline char get(){
if(iiter==llen)llen=fread(in,1,100000,stdin),iiter=0;
if(llen==0)return EOF;
return in[iiter++];
}
inline int rd(){
char ch=get();while(ch<'0'||ch>'9')ch=get();
int res=0;while(ch>='0'&&ch<='9')res=(res<<3)+(res<<1)+ch-'0',ch=get();
return res;
}
inline void pr(int res){
if(res==0){putchar('0');return;}
static int out[10];int len=0;
while(res)out[len++]=res%10,res/=10;
for(int i=len-1;i>=0;i--)putchar(out[i]+'0');
}
#define fi first
#define se second
#define pb push_back
#define mp make_pair
const int N=1e5+10,M=2e5+10;
int n,m;
vectorg[N];
int id[N],hv[N],sz[N],hd[N],pa[N],dep[N],Pos[N],cnt=0;
void get_hv(int x,int fa){
sz[x]=1;hv[x]=-1;pa[x]=fa;
for(auto to:g[x]){
if(to==fa)continue;
dep[to]=dep[x]+1;
get_hv(to,x);
sz[x]+=sz[to];
if(hv[x]==-1||sz[to]>sz[hv[x]]){
hv[x]=to;
}
}
}
void depo(int x,int fa){
if(hv[x]!=-1){
hd[hv[x]]=hd[x];
Pos[cnt]=hv[x];
id[hv[x]]=cnt++;
depo(hv[x],x);
}
for(auto to:g[x]){
if(to==fa||to==hv[x])continue;
hd[to]=to;
Pos[cnt]=to;
id[to]=cnt++;
depo(to,x);
}
}
class SGT{
public:
class node{
public:
priority_queueq1,q2;
inline void ins(int val){q1.push(val);}
inline void era(int val){q2.push(val);}
inline int top(){
while(!q2.empty()&&q2.top()==q1.top())q1.pop(),q2.pop();
return q1.empty()?-1:q1.top();
}
}ts[N<<2];
void upd_add(int x,int l,int r,int cl,int cr,int val){
if(l==cl&&r==cr){
ts[x].ins(val);
return;
}
int mid=(l+r)>>1;
if(cr<=mid)upd_add(x<<1,l,mid,cl,cr,val);
else if(mid+1<=cl)upd_add(x<<1|1,mid+1,r,cl,cr,val);
else upd_add(x<<1,l,mid,cl,mid,val),upd_add(x<<1|1,mid+1,r,mid+1,cr,val);
}
void upd_del(int x,int l,int r,int cl,int cr,int val){
if(l==cl&&r==cr){
ts[x].era(val);
return;
}
int mid=(l+r)>>1;
if(cr<=mid)upd_del(x<<1,l,mid,cl,cr,val);
else if(mid+1<=cl)upd_del(x<<1|1,mid+1,r,cl,cr,val);
else upd_del(x<<1,l,mid,cl,mid,val),upd_del(x<<1|1,mid+1,r,mid+1,cr,val);
}
int qry(int x,int l,int r,int pos){
if(l==r)return ts[x].top();
int mid=(l+r)>>1;
if(pos<=mid)return max(qry(x<<1,l,mid,pos),ts[x].top());
else return max(qry(x<<1|1,mid+1,r,pos),ts[x].top());
}
}T;
int tp[M],A[M],B[M],w[M],t[M],pos[M],ans[M];
int lca(int u,int v){
while(hd[u]!=hd[v]){
if(dep[hd[u]]>dep[hd[v]])swap(u,v);
v=pa[hd[v]];
}
return dep[u] >v,int tmp
sort(v.begin(),v.end());
if(0 >ve;
int u=A[i],v=B[i],r=lca(u,v);
while(hd[u]!=hd[r]){
ve.pb(mp(id[hd[u]],id[u]));
u=pa[hd[u]];
}
ve.pb(mp(id[r],id[u]));
while(hd[v]!=hd[r]){
ve.pb(mp(id[hd[v]],id[v]));
v=pa[hd[v]];
}
if(id[r]+1<=id[v])ve.pb(mp(id[r]+1,id[v]));
op_ins(ve,i);
}
void op_del(vector >v,int tmp){
sort(v.begin(),v.end());
if(0 >ve;
while(hd[u]!=hd[r]){
ve.pb(mp(id[hd[u]],id[u]));
u=pa[hd[u]];
}
ve.pb(mp(id[r],id[u]));
while(hd[v]!=hd[r]){
ve.pb(mp(id[hd[v]],id[v]));
v=pa[hd[v]];
}
if(id[r]+1<=id[v])ve.pb(mp(id[r]+1,id[v]));
op_del(ve,i);
}
vectorQ[M];
int main(){
n=rd();m=rd();
for(int i=0;i