#include
#include
#include
#include
typedef unsigned long long ull;
int const maxn=100110,maxm=100110;
int n,q,p,root;
//*******以下为存图部分********
struct E
{
int to,next;
E(int to=0,int next=0):
to(to),next(next){}
}e[maxn<<1];
int head[maxn],cnt2;
void rem()
{
memset(head,-1,sizeof(head));
}
void add(int u,int v)
{
e[++cnt2]=(E){v,head[u]};
head[u]=cnt2;
}
//*********以下为剖树部分**********
int dep[maxn],fa[maxn],size[maxn],hson[maxn];
int id[maxn],top[maxn],w[maxn],val[maxn],tot;
int pre_dfs(int u,int f)
{
dep[u]=dep[f]+1;
fa[u]=f;
size[u]=1;
int maxson=-1;
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(v==f)
continue;
size[u]+=pre_dfs(v,u);
if(maxson=rr)
//喜闻乐见的错误
update(a[u].lc,l,mid,ll,rr,dlt);
else if(mid=ll&&mid=ll&&middep[y])
std::swap(x,y);
update(1,1,n,id[x],id[y],dlt);
}
int TL_query(int x,int y)
{
int ans=0;
while(top[x]!=top[y])
{
if(dep[top[x]]dep[y])
std::swap(x,y);
ans=(ans%p+query(1,1,n,id[x],id[y]))%p;
return ans;
}
//********以下为线段树维护子树信息********
void Tr_update(int x,int dlt)
{
update(1,1,n,id[x],id[x]+size[x]-1,dlt);
//一直不懂
}
int Tr_query(int x)
{
return query(1,1,n,id[x],id[x]+size[x]-1);
}
//**********以下为读入部分***********
void read()
{
scanf("%d%d%d%d",&n,&q,&root,&p);
for(int i=1;i<=n;i++)
scanf("%d",&val[i]),val[i]%=p;
for(int x,y,i=1;i
#include
#include
#include
#include
typedef unsigned long long ull;
int const maxn=500100,maxm=500100;
int n,q,root;
//******************************************
struct E
{
int to,next;
E(int to=0,int next=0):
to(to),next(next){}
}e[maxm<<1];
int head[maxn],cnt;
void add(int u,int v)
{
e[++cnt]=(E){v,head[u]};
head[u]=cnt;
}
//******************************************
int dep[maxn],size[maxn],hson[maxn],fa[maxn];
int top[maxn],tot;
int pre_dfs(int u,int f)
{
dep[u]=dep[f]+1;
fa[u]=f;
size[u]=1;
int maxson=-1;
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if(v==f)
continue;
size[u]+=pre_dfs(v,u);
if(maxsondep[y])
std::swap(x,y);
return x;
}
int main()
{
scanf("%d%d%d",&n,&q,&root);
for(int x,y,i=1;i
!这道题要好好说说了,喵的坑了我一上午
虽说一看就是道最大生成树+树剖维护链上最小值的水题,但介于这是我打的第一道树剖题,还是出了不少岔子
注意事项
1、这题需要化边权为点权,显然是要将边权下放到儿子上,因为对于一个点来说父亲只有一个,儿子可能有多个
2、根节点要特殊处理!,因为没有深度比根更小的点,所以根不会也不能对答案产生影响,对于这道题来说,需要赋一个极大值
3、该图不保证联通,所以要建最大生成森林,而且要以多个点为根节点跑dfs
4、不要把并查集的fa1[]和维护树点父亲的fa2[]搞混!!!
5、最大的坑点!当我以为可以线段树暴力查询的时候,我惊奇的发现待查询的两个点的LCA会对结果产生影响,这是因为每个点的点权实际上存的是连向父亲边的权,因此我们需要把LCA的点权给干掉,因为压根就不会经过那条边,具体操作为把LCA的id+1,因为LCA的深度小,作为查询的左区间
6、哈哈哈哈哈哈你以为这样就结束了?LCA的深度一定小么?当两条轻链都向上跳的时候有可能会跳到同一个点,需要特判
#include
#include
#include
#include
typedef unsigned long long ull;
int const maxn=500100,maxm=500100,inf=0x1f1f1f1f;
int n,m,q,num,root[maxn],cur;
//*******************************************
struct E
{
int to,next,w;
E(int to=0,int next=0,int w=0):
to(to),next(next),w(w){}
}e[maxn<<1];
int head[maxn],cnt;
void add(int u,int v,int w)
{
e[++cnt]=(E){v,head[u],w};
head[u]=cnt;
// printf("%d%d,",v,u);
}
//*******************************************
int dep[maxn],size[maxn],fa[maxn],hson[maxn];
int top[maxn],id[maxn],w[maxn],val[maxn],tot;
int pre_dfs(int u,int ff)
{
dep[u]=dep[ff]+1;
fa[u]=ff;
size[u]=1;
int maxson=-1;
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to,w=e[i].w;
if(v==ff)
continue;
val[v]=w;
size[u]+=pre_dfs(v,u);
if(maxson=ll&&mid=rr?query(a[u].lc,l,mid,ll,rr):query(a[u].rc,mid+1,r,ll,rr));
//ll是待修改区间,l是当前处理到的区间,不要混淆!
}
//*******************************************
int TL_query(int x,int y)
{
int ans=inf;
while(top[x]!=top[y])
{
if(dep[top[x]]dep[y])
std::swap(x,y);
if(x!=y)
//深坑!
ans=std::min(ans,query(1,1,n,id[x]+1,id[y]));
return ans;
}
//*******************************************
struct RE
{
int u,v,w;
int operator <(const RE &b)const
{
return w>b.w;
}
}ee[maxm];
int f[maxn];
int find(int x)
{
return x==f[x]?x:f[x]=find(f[x]);
}
void kruskal()
{
for(int i=1;i<=n;i++)
f[i]=i;
std::sort(ee+1,ee+1+m);
for(int i=1;i<=m;i++)
{
int w=ee[i].w,u=ee[i].u,v=ee[i].v,
fu=find(u),
fv=find(v);
// printf("%d %d,,,\n",fu,fv);
if(fu==fv)
continue;
f[fu]=fv;
// printf("!%d %d:%d\n",u,v,w);
add(u,v,w),add(v,u,w);
}
}
//*******************************************
int main()
{
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&ee[i].u,&ee[i].v,&ee[i].w);
kruskal();
// /*
for(int i=1;i<=n;i++)
if(!size[i])
dep[i]=-1,pre_dfs(i,0),val[i]=inf,root[++cur]=i;
for(int i=1;i<=cur;i++)
mark_dfs(root[i],root[i]);
// for(int i=1;i<=n;i++)
// printf("!%d %d\n",i,id[i]);
build(1,1,n);
// */
scanf("%d",&q);
for(int x,y,i=1;i<=q;i++)
{
scanf("%d%d",&x,&y);
if(find(x)!=find(y))
{
printf("-1\n");
continue;
}
printf("%d\n",TL_query(x,y));
}
return 0;
}
感觉我是真的蠢…
明知道是求区间最值和求和完全弄混了…
#include
#include
#include
#include
typedef unsigned long long ull;
int const maxn=50100,maxm=50100,inf=0x1f1f1f1f;
int n,q;
// ********************************
struct E
{
int to,next;
E(int to=0,int next=0):
to(to),next(next){}
}e[maxn<<1];
int head[maxn],cnt;
void add(int u,int v)
{
e[++cnt]=(E){v,head[u]};
head[u]=cnt;
}
//*********************************
int dep[maxn],size[maxn],fa[maxn],hson[maxn];
int id[maxn],top[maxn],tot;
int pre_dfs(int u,int f)
{
dep[u]=dep[f]+1;
fa[u]=f;
size[u]=1;
int maxson=-1;
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if(v==f)
continue;
size[u]+=pre_dfs(v,u);
if(size[v]>maxson)
{
maxson=size[v];
hson[u]=v;
}
}
return size[u];
}
void mark_dfs(int u,int topf)
{
id[u]=++tot;
top[u]=topf;
if(size[u]==1)
return;
mark_dfs(hson[u],topf);
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if(!id[v])
mark_dfs(v,v);
}
}
//*********************************
struct Tree
{
int lc,rc,max,tag;
}a[maxn<<1];
int t=1;
void pushup(int u)
{
a[u].max=std::max(a[a[u].lc].max,a[a[u].rc].max);
}
void pushdown(int u,int l,int r)
{
int tag=a[u].tag,lc=a[u].lc,rc=a[u].rc;
a[lc].max+=tag,a[lc].tag+=tag;
a[rc].max+=tag,a[rc].tag+=tag;
a[u].tag=0;
}
void build(int u,int l,int r)
{
if(l==r)
return;
int mid=(l+r)/2;
a[u].lc=++t;build(a[u].lc,l,mid);
a[u].rc=++t;build(a[u].rc,mid+1,r);
}
void update(int u,int l,int r,int ll,int rr)
{
if(l==ll&&r==rr)
{
a[u].max++;
a[u].tag++;
// printf("!!!%d %d %d\n",l,r,a[u].max);
return;
}
pushdown(u,l,r);
int mid=(l+r)/2;
if(mid>=rr)
update(a[u].lc,l,mid,ll,rr);
else if(middep[y])
std::swap(x,y);
update(1,1,n,id[x],id[y]);
}
//*********************************
int main()
{
// freopen("in.in","r",stdin);
scanf("%d%d",&n,&q);
for(int x,y,i=1;i
都说这题比较水,其实还是有点东西的,调了一下午…
才不是因为两个三目运算符嵌套太长了一直没看到错…
题目疯狂明示,n-1个关系画出来就是一棵树
用1表示已安装,0表示未安装,
就会发现安装就是对从根到当前节点的树链操作,卸载就是对当前节点的子树操作,具体操作是区间覆盖区间查询
很朴素的思路是在修改前后各查询一次,差值就是答案
然而仔细一想,对子树的查询得到的(1)已安装的个数,已经是答案了,用深度减去对树链的查询就是(0)未安装的个数
以下为坑点:
1、tag的初值为-1,因为0在本题有意义
2、tag只有在不等于-1的时候才能向下传
3、区间覆盖就是把+=改为=
4、习惯问题,节点右移
#include
#include
#include
#include
typedef unsigned long long ull;
int const maxn=1001100,maxm=1001100,inf=0x1f1f1f1f;
int n,q;
//***************************
struct E
{
int to,next;
E(int to=0,int next=0):
to(to),next(next){}
}e[maxn];
int head[maxn],cnt;
void add(int u,int v)
{
e[++cnt]=(E){v,head[u]};
head[u]=cnt;
}
//***************************
int dep[maxn],size[maxn],hson[maxn],fa[maxn];
int id[maxn],top[maxn],tot;
int pre_dfs(int u,int f)
{
dep[u]=dep[f]+1;
size[u]=1;
fa[u]=f;
int maxson=-1;
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if(v==f)
continue;
size[u]+=pre_dfs(v,u);
if(maxsonmid)
update(a[u].rc,mid+1,r,ll,rr,end);
else
update(a[u].lc,l,mid,ll,mid,end),update(a[u].rc,mid+1,r,mid+1,rr,end);
pushup(u);
}
int query(int u,int l,int r,int ll,int rr)
{
if(l==ll&&r==rr)
return a[u].sum;
if(a[u].tag!=-1)
pushdown(u,l,r);
int mid=(l+r)/2;
return mid>=ll&&mid=rr?query(a[u].lc,l,mid,ll,rr):query(a[u].rc,mid+1,r,ll,rr));
}
//***************************
int TL_query(int x)
{
int ans=dep[x],y=1;
while(top[x]!=top[y])
{
// printf("!!!%d %d\n",id[top[x]],id[x]);
ans-=query(1,1,n,id[top[x]],id[x]);
update(1,1,n,id[top[x]],id[x],1);
// printf("??????%d %d %d\n",id[x],id[top[x]],query(1,1,n,id[top[x]],id[x]));
// printf("~~~%d\n",query(1,1,n,7,7));
x=fa[top[x]];
}
std::swap(x,y);
ans-=query(1,1,n,id[x],id[y]);
// printf("~~~%d\n",query(1,1,n,id[x],id[y]));
update(1,1,n,id[x],id[y],1);
// printf("!!!!!!%d %d %d\n",id[x],id[y],query(1,1,n,id[x],id[y]));
return ans;
}
int Tr_query(int x)
{
int ans=query(1,1,n,id[x],id[x]+size[x]-1);
update(1,1,n,id[x],id[x]+size[x]-1,0);
return ans;
}
int main()
{
scanf("%d",&n);
for(int x,i=1;i>op;
scanf("%d",&x);x++;
// printf("%c\n",op[0]);
if(op[0]=='i')
printf("%d\n",TL_query(x));
else
printf("%d\n",Tr_query(x));
}
return 0;
}