2025.1.7 做题记录
CF600E
dsu on tree 裸题。
P3899
考虑对
那么问题就变成了,求
P3703
染上一个没有染过的点比较麻烦。不如直接染成
我们将两个问题分开考虑。第一个使用树剖维护颜色段,第二个使用普通线段树维护区间最大值。时间复杂度
代码
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
const int N=2e5+10;
int n,m;
int val[N];
vector<int> e[N];
int mson[N],siz[N],top[N];
int id[N],dfn[N],cnt,dep[N],f[N];
int jump[N][22];
struct Tree1{
int l,r;
int cl,cr;
int val,tag;
}tr[N<<2];
struct Tree2{
int l,r;
int tag,mx;
}tr_[N<<2];
int Top[N],Bot[N];
il void up_(int u){
tr_[u].mx=max(tr_[ls(u)].mx,tr_[rs(u)].mx);
return ;
}
il void down_(int u){
if(!tr_[u].tag) return ;
tr_[ls(u)].tag+=tr_[u].tag,
tr_[rs(u)].tag+=tr_[u].tag;
tr_[ls(u)].mx+=tr_[u].tag,
tr_[rs(u)].mx+=tr_[u].tag;
return tr_[u].tag=0,void(0);
}
il void build_(int u,int l,int r){
tr_[u].l=l,tr_[u].r=r;
if(l==r) return tr_[u].mx=dep[id[l]],void(0);
int mid=l+r>>1;
build_(ls(u),l,mid),build_(rs(u),mid+1,r);
return up_(u),void(0);
}
il void modify_(int u,int l,int r,int x){
if(tr_[u].l>=l&&tr_[u].r<=r){
tr_[u].mx+=x,tr_[u].tag+=x;
return ;
}
down_(u);
int mid=tr_[u].l+tr_[u].r>>1;
if(l<=mid) modify_(ls(u),l,r,x);
if(mid< r) modify_(rs(u),l,r,x);
return up_(u),void(0);
}
il int query_(int u,int l,int r){
if(tr_[u].l>=l&&tr_[u].r<=r) return tr_[u].mx;
down_(u);
int mid=tr_[u].l+tr_[u].r>>1,mx=0;
if(l<=mid) mx=max(mx,query_(ls(u),l,r));
if(mid< r) mx=max(mx,query_(rs(u),l,r));
return mx;
}
il void up(Tree1 &u,Tree1 x,Tree1 y){
u.val=x.val+y.val-(x.cr==y.cl);
u.cl=x.cl,u.cr=y.cr;
return ;
}
il void down(int u){
if(!tr[u].tag) return ;
tr[ls(u)].tag=tr[rs(u)].tag=tr[u].tag;
tr[ls(u)].cl=tr[ls(u)].cr=tr[u].tag;
tr[rs(u)].cl=tr[rs(u)].cr=tr[u].tag;
tr[ls(u)].val=tr[rs(u)].val=1;
return tr[u].tag=0,void(0);
}
il void build(int u,int l,int r){
tr[u].l=l,tr[u].r=r;
if(l==r) return tr[u].cl=tr[u].cr=id[l],tr[u].val=1,void(0);
int mid=l+r>>1;
build(ls(u),l,mid),build(rs(u),mid+1,r);
return up(tr[u],tr[ls(u)],tr[rs(u)]),void(0);
}
il void modify(int u,int l,int r,int x){
if(tr[u].l>=l&&tr[u].r<=r){
tr[u].val=1,tr[u].tag=x;
tr[u].cl=tr[u].cr=x;
return ;
}
down(u);
int mid=tr[u].l+tr[u].r>>1;
if(l<=mid) modify(ls(u),l,r,x);
if(mid< r) modify(rs(u),l,r,x);
return up(tr[u],tr[ls(u)],tr[rs(u)]),void(0);
}
il Tree1 query(int u,int l,int r){
if(tr[u].l>=l&&tr[u].r<=r) return tr[u];
down(u);
int mid=tr[u].l+tr[u].r>>1;
if(l<=mid&&mid< r){
Tree1 V;
memset(&V,0,sizeof(V));
up(V,query(ls(u),l,r),query(rs(u),l,r));
return V;
}
if(l<=mid) return query(ls(u),l,r);
if(mid< r) return query(rs(u),l,r);
debug();
}
il int Query_(int u,int x){
if(tr[u].l==tr[u].r) return tr[u].cl;
down(u);
int mid=tr[u].l+tr[u].r>>1;
if(x<=mid) return Query_(ls(u),x);
if(mid< x) return Query_(rs(u),x);
}
il void dfs1(int u,int fa){
int msiz=0;
jump[u][0]=fa;
for(re int i=1;i<22;++i) jump[u][i]=jump[jump[u][i-1]][i-1];
f[u]=fa,dep[u]=dep[fa]+1,mson[u]=-1,siz[u]=1;
for(auto v:e[u])
if(v!=fa){
dfs1(v,u),siz[u]+=siz[v];
if(msiz<siz[v]) msiz=siz[v],mson[u]=v;
}
return ;
}
il void dfs2(int u,int Tp){
id[++cnt]=u,dfn[u]=cnt;
top[u]=Tp;
if(~mson[u]) dfs2(mson[u],Tp);
for(auto v:e[u])
if(v!=f[u]&&v!=mson[u]){
dfs2(v,v);
}
return ;
}
il int Up(int u,int S){
int p=0;
while(S){
if(S&1) u=jump[u][p];
S>>=1,++p;
}
return u;
}
il void Modify(int x,int y,int z){
int lst=0;int To=0;
int X=x,Y=y,Z=z;Bot[z]=x,Top[z]=1;
while(x){
int Col=Query_(1,dfn[x]);
int Val=query_(1,dfn[x],dfn[x]);
int id1=top[x],id2=Top[Col];
if(dep[id1]<dep[id2]){
modify(1,dfn[id2],dfn[x],z);
modify_(1,dfn[id2],dfn[id2]+siz[id2]-1,-(Val-1));
if(lst) modify_(1,dfn[lst],dfn[lst]+siz[lst]-1,(Val-1));
}
else{
modify(1,dfn[id1],dfn[x],z);
modify_(1,dfn[id1],dfn[id1]+siz[id1]-1,-(Val-1));
if(lst) modify_(1,dfn[lst],dfn[lst]+siz[lst]-1,(Val-1));
}
if(x!=Bot[Col]){
int x_=Up(Bot[Col],dep[Bot[Col]]-dep[x]-1);
if(x_!=lst) modify_(1,dfn[x_],dfn[x_]+siz[x_]-1,1),To=x_;
}
if(dep[id2]<dep[id1]) x=f[id1],lst=id1;
else x=f[id2],lst=id2,Top[Col]=To;
}
return ;
}
il int Query(int x,int y){
Tree1 ans1,ans2;
memset(&ans1,0,sizeof(ans1));
memset(&ans2,0,sizeof(ans2));
while(top[x]!=top[y]){
if(dep[top[x]]>=dep[top[y]]){
Tree1 ans=query(1,dfn[top[x]],dfn[x]);
x=f[top[x]];
up(ans1,ans,ans1);
}
else{
Tree1 ans=query(1,dfn[top[y]],dfn[y]);
y=f[top[y]];
up(ans2,ans,ans2);
}
}
if(dep[x]>=dep[y]) up(ans1,query(1,dfn[y],dfn[x]),ans1);
if(dep[x]< dep[y]) up(ans2,query(1,dfn[x],dfn[y]),ans2);
swap(ans1.cl,ans1.cr);
up(ans2,ans1,ans2);
return ans2.val;
}
il void solve(){
n=rd,m=rd;
for(re int i=1;i< n;++i){
int u=rd,v=rd;
e[u].push_back(v),
e[v].push_back(u);
}
dfs1(1,0),top[1]=1,dfs2(1,1);
build(1,1,n),build_(1,1,n);
for(re int i=1;i<=n;++i) Top[i]=Bot[i]=i;int Cnt=n;
while(m--){
int op=rd;
if(op==1){
int x=rd;
Modify(x,1,++Cnt);
}
else if(op==2){
int x=rd,y=rd;
printf("%lld\n",Query(x,y));
}
else if(op==3){
int x=rd;
printf("%lld\n",query_(1,dfn[x],dfn[x]+siz[x]-1));
}
}
return ;
}
CF1280C
考虑对于一条连接
CF1304E
先考虑如果没有加边时的情况。那么很显然的,只要
CF1650G
与最短路距离不超过
CF489F
可以先把每一列的
CF659G
注意到我们切下来的是一个四联通块。那么记
CF1418G
唐诗。
有个典 trick,判定一段区间内每个数是否出现偶数次可以直接全部异或起来。只要是
那么这题可以直接仿照这个思路。考虑分治。我们对
CF1744F
考虑什么样的区间满足条件。区间内的中位数
CF1702G1/G2
先不考虑
注意到
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· Trae初体验