声明:由于本人能力尚不优 故无法做出解释文章 此文仅为自己日记 感谢你的阅读
作为队里的数据结构选手 2019西安邀请赛的E题 竟然在有机时的情况下 想到了线段树log^2的拆位做法 但是题目路径把自己问懵逼了 啥? 啥是最短路? 点和点之间最短路是啥?
于是 这名数据结构小菜鸡只好回来恶补某个维护树上点和点直接最短路的东西 ---- 叔脸剖分(这名数据结构小菜鸡没脸啦
我们只要维护一下一个max 和 sum 即可轻松AC
/*
if you can't see the repay
Why not just work step by step
rubbish is relaxed
to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod = (int)1e9+7;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];
inline int read()
{
int date = 0,m = 1; char ch = 0;
while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();
if(ch=='-'){m = -1; ch = getchar();}
while(ch>='0' && ch<='9')
{
date = date*10+ch-'0';
ch = getchar();
}return date*m;
}
const int MAX_N = 30025;
int arr[MAX_N],p[MAX_N],top[MAX_N],eid,cnt,Rank[MAX_N],id[MAX_N],sz[MAX_N],son[MAX_N],maxx[MAX_N<<2],s[MAX_N<<2],depth[MAX_N],fa[MAX_N];
int n;
void init()
{
memset(p,-1,sizeof(p));
eid = 0;
}
struct edge
{
int v,next;
}e[MAX_N<<1];
void add(int u,int v)
{
e[eid].v =v ;
e[eid].next = p[u];
p[u] = eid++;
}
int Max(int a,int b){return a > b?a:b;}
void up(int rt)
{
maxx[rt] = Max(maxx[rt<<1],maxx[rt<<1|1]);
s[rt] = s[rt<<1]+s[rt<<1|1];
}
void build(int rt,int l,int r)
{
if(l==r)
{
s[rt] = maxx[rt] = arr[Rank[l]];
return;
}
int mid = (l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
up(rt);
}
void update(int rt,int l,int r,int x,int v)
{
if(l==r)
{
maxx[rt] = s[rt] = v;
return;
}
int mid = (l+r)>>1;
if(x<=mid) update(rt<<1,l,mid,x,v);
else update(rt<<1|1,mid+1,r,x,v);
up(rt);
}
int query(int rt,int l,int r,int x,int y,int flag)
{
if(x<=l&&r<=y)
{
if(flag==0) return maxx[rt];
return s[rt];
}
int mid = (l+r)>>1;
if(x>mid) return query(rt<<1|1,mid+1,r,x,y,flag);
else if(y<=mid) return query(rt<<1,l,mid,x,y,flag);
else
{
if(flag==0) return Max(query(rt<<1,l,mid,x,y,flag),query(rt<<1|1,mid+1,r,x,y,flag));
return query(rt<<1,l,mid,x,y,flag)+query(rt<<1|1,mid+1,r,x,y,flag);
}
}
void dfs1(int x,int fath)
{
fa[x] = fath;
depth[x] = depth[fath]+1;
sz[x] = 1;
for(int i = p[x];i+1;i=e[i].next)
{
int v = e[i].v;
if(v==fath) continue;
dfs1(v,x);
sz[x]+=sz[v];
if(sz[son[x]]<sz[v]) son[x] = v;
}
}
void dfs2(int u,int t)
{
top[u] = t;
id[u] = ++cnt;
Rank[cnt] = u;
if(!son[u]) return;
dfs2(son[u],t);
for(int i = p[u];i+1;i=e[i].next)
{
int v= e[i].v;
if(v!=son[u]&&v!=fa[u]) dfs2(v,v);
}
}
int Sum(int x,int y)
{
int ans = 0;
while(top[x]!=top[y])
{
if(depth[top[x]]<depth[top[y]]) swap(x,y);
ans+=query(1,1,n,id[top[x]],id[x],1);
x = fa[top[x]];
}
if(id[x]>id[y]) swap(x,y);
ans+=query(1,1,n,id[x],id[y],1);
return ans;
}
int sum(int x,int y)
{
int ans = -30001;
while(top[x]!=top[y])
{
if(depth[top[x]]<depth[top[y]]) swap(x,y);
ans = Max(ans,query(1,1,n,id[top[x]],id[x],0));
x = fa[top[x]];
}
if(id[x]>id[y]) swap(x,y);
ans = Max(ans,query(1,1,n,id[x],id[y],0));
return ans;
}
/*namespace sgt
{
#define mid ((l+r)>>1)
#undef mid
}*/
/*int root[MAX_N],cnt,sz;
namespace hjt
{
#define mid ((l+r)>>1)
struct node{int l,r,maxx;}T[MAX_N*40];
#undef mid
}*/
int main()
{
//ios::sync_with_stdio(false);
//freopen("a.txt","r",stdin);
//freopen("b.txt","w",stdout);
int a,b,m,x,y;
n = read();
char opt[25];
init();
for(int i = 1;i<n;++i)
{
a = read();b=read();
add(a,b);add(b,a);
}
for(int i = 1;i<=n;++i) arr[i] = read();
dfs1(1,0);
dfs2(1,1);
build(1,1,n);
m = read();
for(int i = 1;i<=m;++i)
{
scanf("%s",opt);
if(opt[0]=='C')
{
x = read();y=read();
update(1,1,n,id[x],y);
}
else
{
if(opt[1]=='M')
{
x = read();y = read();
printf("%d\n",sum(x,y));
}
else
{
x = read();y=read();
printf("%d\n",Sum(x,y));
}
}
}
//fclose(stdin);
//fclose(stdout);
//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
return 0;
}
用到了树链剖分的第一个dfs序 因为dfs序是连续的 你记得用小的-1 而不是大的dfn 因为这两个父子可能不相连 举个例子 父亲的右儿子 因为这个WA了一发
//http://cogs.pro:8080/cogs/problem/problem.php?pid=vXNzykekV
/*
if you can't see the repay
Why not just work step by step
rubbish is relaxed
to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod = (int)1e9+7;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];
inline int read()
{
int date = 0,m = 1; char ch = 0;
while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();
if(ch=='-'){m = -1; ch = getchar();}
while(ch>='0' && ch<='9')
{
date = date*10+ch-'0';
ch = getchar();
}return date*m;
}
const int MAX_N = 100025;
int a[MAX_N],b[MAX_N],p[MAX_N],eid,cnt,low[MAX_N],sz[MAX_N],depth[MAX_N],Rank[MAX_N],Point[MAX_N],high[MAX_N];
ll arr[MAX_N];
ll Max(ll a,ll b) {return a>b?a:b;}
ll Min(ll a,ll b) {return a<b?a:b;}
void init()
{
memset(p,-1,sizeof(p));
eid = 0;
}
struct edge
{
int next,v,d;
}e[MAX_N<<1];
void add(int u,int v,int d)
{
e[eid].d = d;
e[eid].v = v;
e[eid].next = p[u];
p[u] = eid++;
}
void dfs(int x,int fa)
{
sz[x] = 1;
depth[x] = depth[fa]+1;
low[x] = ++cnt;
Rank[cnt] = x;
for(int i = p[x];i+1;i=e[i].next)
{
int v = e[i].v;
if(v==fa) continue;
Point[e[i].d] = v;
dfs(v,x);
sz[x]+=sz[v];
}
high[x] = cnt;
}
namespace sgt
{
#define mid ((l+r)>>1)
ll maxx[MAX_N<<2],minn[MAX_N<<2];
void up(int rt)
{
maxx[rt] = Max(maxx[rt<<1],maxx[rt<<1|1]);
minn[rt] = Min(minn[rt<<1],minn[rt<<1|1]);
}
void build(int rt,int l,int r)
{
if(l==r)
{
maxx[rt] = minn[rt] = arr[Rank[l]];
return;
}
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
up(rt);
}
void update(int rt,int l,int r,int x,int v)
{
if(l==r)
{
maxx[rt] = minn[rt] = v;
return;
}
if(x<=mid) update(rt<<1,l,mid,x,v);
else update(rt<<1|1,mid+1,r,x,v);
up(rt);
}
ll query(int rt,int l,int r,int x,int y,int flag)
{
if(x>y) if(flag==0) return 0;
else return 100000005ll;
if(x<=l&&r<=y)
{
if(flag==0) return maxx[rt];
return minn[rt];
}
if(x>mid) return query(rt<<1|1,mid+1,r,x,y,flag);
else if(y<=mid) return query(rt<<1,l,mid,x,y,flag);
else
{
if(flag==0) return Max(query(rt<<1,l,mid,x,y,flag),query(rt<<1|1,mid+1,r,x,y,flag));
return Min(query(rt<<1,l,mid,x,y,flag),query(rt<<1|1,mid+1,r,x,y,flag));
}
}
#undef mid
}
/*int root[MAX_N],cnt,sz;
namespace hjt
{
#define mid ((l+r)>>1)
struct node{int l,r,maxx;}T[MAX_N*40];
#undef mid
}*/
int main()
{
//ios::sync_with_stdio(false);
freopen("westward.in","r",stdin);
freopen("westward.out","w",stdout);
int x,y,n,Q;
char opt[25];
n = read();Q = read();
for(int i = 1;i<=n;++i) scanf("%lld",&arr[i]);
init();
for(int i = 1;i<n;++i)
{
a[i] = read();b[i] = read();
add(a[i],b[i],i);add(b[i],a[i],i);
}
dfs(1,0);
sgt::build(1,1,n);
for(int i = 1;i<=Q;++i)
{
scanf("%s",opt);
if(opt[0]=='Q')
{
x = read();
ll maxx1,maxx2,minn1,minn2;
int P = a[x],P_ = b[x];
if(low[P]>low[P_]) swap(P,P_);
maxx1 = Max(sgt::query(1,1,n,1,low[P_]-1,0),sgt::query(1,1,n,high[P_]+1,n,0));
minn1 = Min(sgt::query(1,1,n,1,low[P_]-1,1),sgt::query(1,1,n,high[P_]+1,n,1));
maxx2 = sgt::query(1,1,n,low[P_],high[P_],0);
minn2 = sgt::query(1,1,n,low[P_],high[P_],1);
printf("%lld\n",minn1*maxx1+minn2*maxx2);
}
else
{
x = read();y= read();
sgt::update(1,1,n,low[x],y);
}
}
//fclose(stdin);
//fclose(stdout);
//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
return 0;
}
BZOJ2243
这题数颜色 大家是不是对线段树统计颜色部分都会
然后为了让我们好写 我们顺便用树链剖分维护一下lca
这样你就不用swap 因为你一旦swap 颜色左右必须要考虑
你考虑两个点各自到lca 因为从底向上 所以不用swap
/*
if you can't see the repay
Why not just work step by step
rubbish is relaxed
to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod = (int)1e9+7;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];
inline int read()
{
int date = 0,m = 1; char ch = 0;
while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();
if(ch=='-'){m = -1; ch = getchar();}
while(ch>='0' && ch<='9')
{
date = date*10+ch-'0';
ch = getchar();
}return date*m;
}
/*namespace sgt
{
#define mid ((l+r)>>1)
#undef mid
}*/
/*int root[MAX_N],cnt,sz;
namespace hjt
{
#define mid ((l+r)>>1)
struct node{int l,r,maxx;}T[MAX_N*40];
#undef mid
}*/
const int MAX_N = 100025;
int n,cnt,s[MAX_N<<2],rnum[MAX_N<<2],lnum[MAX_N<<2],col[MAX_N<<2],p[MAX_N],eid ,fa[MAX_N],sz[MAX_N],depth[MAX_N],son[MAX_N],Rank[MAX_N],top[MAX_N],id[MAX_N],arr[MAX_N];
void init()
{
memset(p,-1,sizeof(p));
eid = 0;
}
void up(int rt)
{
lnum[rt] = lnum[rt<<1];
rnum[rt] = rnum[rt<<1|1];
if(lnum[rt<<1|1]==rnum[rt<<1]) s[rt] = s[rt<<1]+s[rt<<1|1]-1;
else s[rt] = s[rt<<1] +s[rt<<1|1];
}
void build(int rt,int l,int r)
{
col[rt] = lnum[rt] = rnum[rt] = -1;s[rt] = 0;
if(l==r)
{
lnum[rt] = rnum[rt] = arr[Rank[l]];
s[rt] = 1;
return ;
}
int mid = (l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
up(rt);
}
void down(int rt,int l,int r)
{
if(col[rt]!=-1)
{
col[rt<<1] = col[rt<<1|1] = col[rt];
s[rt<<1] = s[rt<<1|1] = 1;
lnum[rt<<1] = lnum[rt<<1|1] = rnum[rt<<1] = rnum[rt<<1|1] = col[rt];
col[rt] = -1;
}
}
void update(int rt,int l,int r,int x,int y,int v)
{
if(x<=l&&r<=y)
{
lnum[rt] = rnum[rt] = col[rt] = v;
s[rt] = 1;
return ;
}
down(rt,l,r);
int mid = (l+r)>>1;
if(x>mid) update(rt<<1|1,mid+1,r,x,y,v);
else if(y<=mid) update(rt<<1,l,mid,x,y,v);
else update(rt<<1,l,mid,x,y,v),update(rt<<1|1,mid+1,r,x,y,v);
up(rt);
}
int query(int rt,int l,int r,int x,int y)
{
if(x<=l&&r<=y)
{
return s[rt];
}
int mid = (l+r)>>1;
down(rt,l,r);
if(x>mid) return query(rt<<1|1,mid+1,r,x,y);
else if(y<=mid) return query(rt<<1,l,mid,x,y);
else
{
if(lnum[rt<<1|1]==rnum[rt<<1]) return (query(rt<<1,l,mid,x,y)+query(rt<<1|1,mid+1,r,x,y) - 1);
else return (query(rt<<1,l,mid,x,y)+query(rt<<1|1,mid+1,r,x,y));
}
}
struct edge
{
int v,next;
}e[MAX_N<<1];
void add(int u,int v)
{
e[eid].v =v;
e[eid].next = p[u];
p[u] = eid++;
}
void dfs1(int x,int fath)
{
sz[x] = 1;
depth[x] = depth[fath]+1;
fa[x] = fath;
for(int i = p[x];i+1;i=e[i].next)
{
int v = e[i].v;
if(v==fath) continue;
dfs1(v,x);
sz[x]+=sz[v];
if(sz[v]>sz[son[x]]) son[x] = v;
}
}
void dfs2(int u,int t)
{
top[u] = t;
id[u] = ++cnt;
Rank[cnt] = u;
if(!son[u])
return;
dfs2(son[u],t);
for(int i = p[u];i+1;i=e[i].next)
{
int v = e[i].v;
if(v!=son[u]&&v!=fa[u])
dfs2(v,v);
}
}
void updates(int x,int y,int c)
{
while(top[x]!=top[y])
{
if(depth[top[x]]<depth[top[y]])
swap(x,y);
update(1,1,n,id[top[x]],id[x],c);
x = fa[top[x]];
}
if(id[x]>id[y])
swap(x,y);
update(1,1,n,id[x],id[y],c);
}
int getl(int rt,int l,int r,int x)
{
if(l==r)
{
return lnum[rt];
}
int mid = (l+r)>>1;
down(rt,l,r);
if(x<=mid) return getl(rt<<1,l,mid,x);
else return getl(rt<<1|1,mid+1,r,x);
}
inline int lca(int x,int y){
int f1=top[x],f2=top[y];
while(f1!=f2) {
if(depth[f1]<depth[f2]) swap(f1,f2),swap(x,y);
x=fa[f1]; f1=top[x];
}
if(depth[x]<depth[y]) swap(x,y);
return y;
}
int sum(int x,int y)
{
int ans = 0,last = -1,now = -1;
while(top[x]!=top[y])
{
now = getl(1,1,n,id[x]);
ans += query(1,1,n,id[top[x]],id[x]);
if(now==last) ans--;
last = getl(1,1,n,id[top[x]]);
x = fa[top[x]];
}
ans+=query(1,1,n,id[y],id[x]);
now = getl(1,1,n,id[x]);
if(now==last) ans--;
return ans;
}
int main()
{
//ios::sync_with_stdio(false);
//freopen("a.txt","r",stdin);
//freopen("b.txt","w",stdout);
int m,a,b,x,y,v;
char opt[5];
n = read();m = read();
init();
for(int i = 1;i<=n;++i) arr[i] = read();
for(int i = 1;i<n;++i)
{
a = read();b=read();
add(a,b);add(b,a);
}
dfs1(1,0);
dfs2(1,1);
build(1,1,n);
for(int i = 1;i<=m;++i)
{
scanf("%s",opt);
if(opt[0]=='C')
{
x = read();y=read();v=read();
updates(x,y,v);
}
else
{
x = read();y = read();
int LCA = lca(x,y);
int ans = sum(x,LCA)+sum(y,LCA);
printf("%d\n",ans-1);
}
}
//fclose(stdin);
//fclose(stdout);
//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
return 0;
}
BZOJ4538
这题应该是我目前熟练剖分做过最难的题了
我们需要维护的是 不经过某段路径的最大值 然后用两个堆
压入堆 和删除堆 删除就是看两个堆顶是不是相同
否则输出压入堆的堆顶
注意 维护的是是不经过某段路径的最大值 这样你在问就可以直接问出来了
/*
if you can't see the repay
Why not just work step by step
rubbish is relaxed
to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod = (int)1e9+7;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];
inline int read()
{
int date = 0,m = 1; char ch = 0;
while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();
if(ch=='-'){m = -1; ch = getchar();}
while(ch>='0' && ch<='9')
{
date = date*10+ch-'0';
ch = getchar();
}return date*m;
}
const int MAX_N = 100011;
const int MAX_M = 200011;
int fa[MAX_N],sz[MAX_N],depth[MAX_N],son[MAX_N],top[MAX_N],id[MAX_N],p[MAX_N],eid,n,ans,cnt;
void init()
{
memset(p,-1,sizeof(p));
eid = 0;
}
struct edge
{
int v,next;
}e[MAX_N<<1];
void add(int u,int v)
{
e[eid].v = v;
e[eid].next = p[u];
p[u] = eid++;
}
struct priority_tree
{
priority_queue<int> q1,q2;
inline void push1(int x) {q1.push(x);}
inline void push2(int x) {q2.push(x);}
inline int top(){
int res = -1;while(!q2.empty()&&(q1.top()==q2.top())) q1.pop(),q2.pop();
if(!q1.empty()) res = q1.top();
return res;
}
}s[MAX_N<<2];
/*namespace sgt
{
#define mid ((l+r)>>1)
#undef mid
}*/
void dfs1(int x,int fath)
{
sz[x] = 1;
fa[x] = fath;
for(int i = p[x];i+1;i=e[i].next)
{
int v = e[i].v;
if(v==fath) continue;
depth[v] = depth[x]+1;
dfs1(v,x);
sz[x]+=sz[v];
if(sz[son[x]]<=sz[v]) son[x] = v;
}
}
void dfs2(int u,int t)
{
top[u] = t;
id[u] = ++cnt;
if(!son[u]) return;
dfs2(son[u],t);
for(int i = p[u];i+1;i=e[i].next)
{
int v = e[i].v;
if(v!=son[u]&&v!=fa[u])
dfs2(v,v);
}
}
struct node
{
int l,r;
bool operator <(const node other) const
{
return l < other.l;
}
}B[MAX_N];
void update(int rt,int l,int r,int x,int y,int v,int flag)
{
if(x<=l&&r<=y)
{
if(flag==0) s[rt].push1(v);
else s[rt].push2(v);
return;
}
int mid = (l+r)>>1;
if(x>mid) update(rt<<1|1,mid+1,r,x,y,v,flag);
else if(y<=mid) update(rt<<1,l,mid,x,y,v,flag);
else update(rt<<1,l,mid,x,y,v,flag),update(rt<<1|1,mid+1,r,x,y,v,flag);
}
void updates(int x,int y,int c,int flag)
{
int f1 = top[x],f2 = top[y],scnt = 0;
while(f1!=f2)
{
if(depth[f1]<depth[f2])
swap(x,y),swap(f1,f2);
B[++scnt].r = id[x],B[scnt].l = id[f1];
x = fa[f1];f1 = top[x];
}
if(depth[x]<depth[y])
swap(x,y);
B[++scnt].r = id[x],B[scnt].l = id[y];
int last = 0;sort(B+1,B+1+scnt);
for(int i = 1;i<=scnt;++i)
{
if(B[i].l-1>=last+1) update(1,1,n,last+1,B[i].l-1,c,flag);
last = B[i].r;
}
if(n>=last+1) update(1,1,n,last+1,n,c,flag);
}
void query(int rt,int l,int r,int x)
{
ans = max(ans,s[rt].top());
if(l==r) return ;
int mid = (l+r)>>1;
if(x<=mid) query(rt<<1,l,mid,x);
else query(rt<<1|1,mid+1,r,x);
}
/*int root[MAX_N],cnt,sz;
namespace hjt
{
#define mid ((l+r)>>1)
struct node{int l,r,maxx;}T[MAX_N*40];
#undef mid
}*/
struct Query{
int x,y,v;
}Q[MAX_M];
int main()
{
//ios::sync_with_stdio(false);
//freopen("a.txt","r",stdin);
//freopen("b.txt","w",stdout);
int m,a,b,ljq,x,y,v;
init();
n = read();m = read();
for(int i = 1;i<n;++i)
{
a=read();b=read();
add(a,b);add(b,a);
}
depth[1] = 1;dfs1(1,0);
cnt = 0;dfs2(1,1);
for(int i = 1;i<=m;++i)
{
ljq = read();
if(ljq==0)
{
x = read();y =read();v=read();
Q[i].x = x;Q[i].y = y;Q[i].v = v;
updates(x,y,v,0);
}
else if(ljq==1)
{
v = read();
updates(Q[v].x,Q[v].y,Q[v].v,1);
}
else
{
v = read();
ans = -1;
query(1,1,n,id[v]);
printf("%d\n",ans);
}
}
//fclose(stdin);
//fclose(stdout);
//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
return 0;
}
P3833
树链剖分乱搞
/*
if you can't see the repay
Why not just work step by step
rubbish is relaxed
to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod = (int)1e9+7;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];
inline int read()
{
int date = 0,m = 1; char ch = 0;
while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();
if(ch=='-'){m = -1; ch = getchar();}
while(ch>='0' && ch<='9')
{
date = date*10+ch-'0';
ch = getchar();
}return date*m;
}
/*namespace sgt
{
#define mid ((l+r)>>1)
#undef mid
}*/
/*int root[MAX_N],cnt,sz;
namespace hjt
{
#define mid ((l+r)>>1)
struct node{int l,r,maxx;}T[MAX_N*40];
#undef mid
}*/
const int MAX_N = 100025;
ll s[MAX_N<<2],col[MAX_N<<2];
int n,p[MAX_N],cnt,eid,id[MAX_N],son[MAX_N],depth[MAX_N],sz[MAX_N],fa[MAX_N],Rank[MAX_N],top[MAX_N];
void init()
{
memset(p,-1,sizeof(p));
eid = 0;
}
struct edge
{
int v,next;
}e[MAX_N<<1];
void add(int u,int v)
{
e[eid].v= v;
e[eid].next = p[u];
p[u] = eid++;
}
void up(int rt)
{
s[rt] =s[rt<<1]+s[rt<<1|1];
}
void build(int rt,int l,int r)
{
s[rt] = col[rt] = 0;
if(l==r)
{
return;
}
int mid = (l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
up(rt);
}
void down(int rt,int l,int r)
{
if(col[rt])
{
int mid = (l+r)>>1;
col[rt<<1]+=col[rt];
col[rt<<1|1]+=col[rt];
s[rt<<1]+=1ll*(mid-l+1)*col[rt];
s[rt<<1|1] += 1ll*(r-mid)*col[rt];
col[rt] = 0;
}
}
void update(int rt,int l,int r,int x,int y,int v)
{
if(x<=l&&r<=y)
{
col[rt]+=v;
s[rt]+=1ll*(r-l+1)*v;
return;
}
down(rt,l,r);
int mid = (l+r)>>1;
if(x>mid) update(rt<<1|1,mid+1,r,x,y,v);
else if(y<=mid) update(rt<<1,l,mid,x,y,v);
else update(rt<<1,l,mid,x,y,v),update(rt<<1|1,mid+1,r,x,y,v);
up(rt);
}
ll query(int rt,int l,int r,int x,int y)
{
if(x<=l&&r<=y)
{
return s[rt];
}
down(rt,l,r);
int mid = (l+r)>>1;
if(x>mid) return query(rt<<1|1,mid+1,r,x,y);
else if(y<=mid) return query(rt<<1,l,mid,x,y);
else return (query(rt<<1,l,mid,x,y)+query(rt<<1|1,mid+1,r,x,y));
}
void dfs1(int x,int fath)
{
depth[x] = depth[fath]+1;
fa[x] = fath;
sz[x] = 1;
for(int i = p[x];i+1;i=e[i].next)
{
int v = e[i].v;
if(v==fath) continue;
dfs1(v,x);
sz[x]+=sz[v];
if(sz[son[x]]<sz[v]) son[x] = v;
}
}
void dfs2(int u,int t)
{
top[u] = t;
id[u] = ++cnt;
Rank[cnt] = u;
if(!son[u]) return;
dfs2(son[u],t);
for(int i = p[u];i+1;i=e[i].next)
{
int v = e[i].v;
if(v!=son[u]&&v!=fa[u])
dfs2(v,v);
}
}
void updates(int x,int y,int c)
{
while(top[x]!=top[y])
{
if(depth[top[x]]<depth[top[y]])
swap(x,y);
update(1,1,n,id[top[x]],id[x],c);
x = fa[top[x]];
}
if(id[x]>id[y]) swap(x,y);
update(1,1,n,id[x],id[y],c);
}
int main()
{
//ios::sync_with_stdio(false);
//freopen("a.txt","r",stdin);
//freopen("b.txt","w",stdout);
int m,a,b,v;
char opt[5];
n = read();
init();
for(int i = 1;i<n;++i)
{
a = read();b=read();a++,b++;
add(a,b);add(b,a);
}
dfs1(1,0);
dfs2(1,1);
build(1,1,n);
m = read();
for(int i = 1;i<=m;++i)
{
scanf("%s",opt);
if(opt[0]=='A')
{
a = read();b=read();v=read();a++;b++;
updates(a,b,v);
}
else
{
a = read();a++;
printf("%lld\n",query(1,1,n,id[a],id[a]+sz[a]-1));
}
}
//fclose(stdin);
//fclose(stdout);
//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
return 0;
}
BZOJ4196
你只要发现 安装都是从这个点到1
删除都是这个点的儿子那么你就很容易搞了
/*
if you can't see the repay
Why not just work step by step
rubbish is relaxed
to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod = (int)1e9+7;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];
inline int read()
{
int date = 0,m = 1; char ch = 0;
while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();
if(ch=='-'){m = -1; ch = getchar();}
while(ch>='0' && ch<='9')
{
date = date*10+ch-'0';
ch = getchar();
}return date*m;
}
const int MAX_N = 100025;
int n,eid,p[MAX_N],cnt,id[MAX_N],s[MAX_N<<2],col[MAX_N<<2],sz[MAX_N],depth[MAX_N],fa[MAX_N],top[MAX_N],son[MAX_N];
void init()
{
memset(p,-1,sizeof(p));
eid = 0;
}
struct edge
{
int v,next;
}e[MAX_N<<1];
void add(int u,int v)
{
e[eid].v = v;
e[eid].next = p[u];
p[u] = eid++;
}
void up(int rt)
{
s[rt] = s[rt<<1]+s[rt<<1|1];
}
void down(int rt,int l,int r)
{
if(col[rt]!=-1)
{
int mid = (l+r)>>1;
s[rt<<1] = (mid-l+1)*col[rt];
s[rt<<1|1] = (r-mid)*col[rt];
col[rt<<1] = col[rt<<1|1] = col[rt];
col[rt] = -1;
}
}
void build(int rt,int l,int r)
{
col[rt] = -1;
if(l==r) {s[rt] = 1;return;}
int mid = (l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
up(rt);
}
void update(int rt,int l,int r,int x,int y,int v)
{
if(x<=l&&r<=y)
{
col[rt] = v;
s[rt] = (r-l+1)*v;
return;
}
down(rt,l,r);
int mid = (l+r)>>1;
if(x>mid) update(rt<<1|1,mid+1,r,x,y,v);
else if(y<=mid) update(rt<<1,l,mid,x,y,v);
else update(rt<<1,l,mid,x,y,v),update(rt<<1|1,mid+1,r,x,y,v);
up(rt);
}
int query(int rt,int l,int r,int x,int y)
{
if(x<=l&&r<=y)
{
return s[rt];
}
down(rt,l,r);
int mid = (l+r)>>1;
if(x>mid) return query(rt<<1|1,mid+1,r,x,y);
else if(y<=mid) return query(rt<<1,l,mid,x,y);
else return (query(rt<<1,l,mid,x,y)+query(rt<<1|1,mid+1,r,x,y));
}
void dfs1(int x,int fath)
{
sz[x] = 1;
depth[x] = depth[fath]+1;
fa[x] = fath;
for(int i = p[x];i+1;i=e[i].next)
{
int v = e[i].v;
if(v==fath) continue;
dfs1(v,x);
sz[x]+=sz[v];
if(sz[son[x]]<sz[v]) son[x] = v;
}
}
void dfs2(int u,int t)
{
top[u] = t;
id[u] = ++cnt;
if(!son[u]) return;
dfs2(son[u],t);
for(int i = p[u];i+1;i=e[i].next)
{
int v = e[i].v;
if(v!=son[u]&&v!=fa[u]) dfs2(v,v);
}
}
int sum(int x,int y)
{
int ans = 0;
while(top[x]!=top[y])
{
if(depth[top[x]]<depth[top[y]]) swap(x,y);
ans+=query(1,1,n,id[top[x]],id[x]);
x = fa[top[x]];
}
if(id[x]>id[y]) swap(x,y);
ans+=query(1,1,n,id[x],id[y]);
return ans;
}
void updates(int x,int y,int c)
{
while(top[x]!=top[y])
{
if(depth[top[x]] < depth[top[y]]) swap(x,y);
update(1,1,n,id[top[x]],id[x],c);
x = fa[top[x]];
}
if(id[x]>id[y]) swap(x,y);
update(1,1,n,id[x],id[y],c);
}
/*namespace sgt
{
#define mid ((l+r)>>1)
#undef mid
}*/
/*int root[MAX_N],cnt,sz;
namespace hjt
{
#define mid ((l+r)>>1)
struct node{int l,r,maxx;}T[MAX_N*40];
#undef mid
}*/
int main()
{
//ios::sync_with_stdio(false);
//freopen("a.txt","r",stdin);
//freopen("b.txt","w",stdout);
int m,a,x;char opt[20];
n = read();
init();
for(int i = 2;i<=n;++i)
{
a = read();a++;
add(a,i);add(i,a);
}
dfs1(1,0);
dfs2(1,1);
build(1,1,n);
m = read();
for(int i = 1;i<=m;++i)
{
scanf("%s%d",opt,&x);
x++;
if(opt[0]=='i')
{
printf("%d\n",sum(1,x));
updates(1,x,0);
}
else
{
printf("%d\n",sz[x]- query(1,1,n,id[x],id[x]+sz[x]-1));
update(1,1,n,id[x],id[x]+sz[x]-1,1);
}
}
//fclose(stdin);
//fclose(stdout);
//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
return 0;
}
P3398
思路也很简单 你区间赋个值 再查一下就行了
以前不会树链剖分这种题估计都要哭爹喊娘了
/*
if you can't see the repay
Why not just work step by step
rubbish is relaxed
to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod = (int)1e9+7;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];
inline int read()
{
int date = 0,m = 1; char ch = 0;
while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();
if(ch=='-'){m = -1; ch = getchar();}
while(ch>='0' && ch<='9')
{
date = date*10+ch-'0';
ch = getchar();
}return date*m;
}
const int MAX_N = 100025;
int Max(int a,int b){return a >b?a:b;}
int n,p[MAX_N],eid,cnt,id[MAX_N],sz[MAX_N],son[MAX_N],fa[MAX_N],maxx[MAX_N<<2],col[MAX_N<<2],top[MAX_N],depth[MAX_N];
void init()
{
memset(p,-1,sizeof(p));
eid = 0;
}
struct edge
{
int v,next;
}e[MAX_N<<1];
void add(int u,int v)
{
e[eid].v = v;
e[eid].next = p[u];
p[u] = eid++;
}
void up(int rt)
{
maxx[rt] = Max(maxx[rt<<1],maxx[rt<<1|1]);
}
void build(int rt,int l,int r)
{
maxx[rt] = 0;col[rt] = -1;
if(l==r) return;
int mid = (l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
}
void down(int rt,int l,int r)
{
if(col[rt]!=-1)
{
maxx[rt<<1] = maxx[rt<<1|1] = col[rt];
col[rt<<1] = col[rt<<1|1] = col[rt];
col[rt] = -1;
}
}
void update(int rt,int l,int r,int x,int y,int v)
{
if(x<=l&&r<=y)
{
maxx[rt] = v;
col[rt] = v;
return ;
}
down(rt,l,r);
int mid = (l+r)>>1;
if(x>mid) update(rt<<1|1,mid+1,r,x,y,v);
else if(y<=mid) update(rt<<1,l,mid,x,y,v);
else update(rt<<1,l,mid,x,y,v),update(rt<<1|1,mid+1,r,x,y,v);
up(rt);
}
int query(int rt,int l,int r,int x,int y)
{
if(x<=l&&r<=y)
{
return maxx[rt];
}
down(rt,l,r);
int mid = (l+r)>>1;
if(x>mid) return query(rt<<1|1,mid+1,r,x,y);
else if(y<=mid) return query(rt<<1,l,mid,x,y);
else return Max(query(rt<<1,l,mid,x,y),query(rt<<1|1,mid+1,r,x,y));
}
void dfs1(int x,int fath)
{
depth[x] = depth[fath]+1;
fa[x] = fath;
sz[x] = 1;
for(int i = p[x];i+1;i=e[i].next)
{
int v = e[i].v;
if(v==fath) continue;
dfs1(v,x);
sz[x]+=sz[v];
if(sz[son[x]]<sz[v]) son[x] = v;
}
}
void dfs2(int u,int t)
{
top[u] = t;
id[u] = ++cnt;
if(!son[u]) return;
dfs2(son[u],t);
for(int i = p[u];i+1;i=e[i].next)
{
int v = e[i].v;
if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
}
}
int sum(int x,int y)
{
int ans = 0;
while(top[x]!=top[y])
{
if(depth[top[x]]<depth[top[y]]) swap(x,y);
ans = Max(ans,query(1,1,n,id[top[x]],id[x]));
x=fa[top[x]];
}
if(id[x]>id[y]) swap(x,y);
ans = Max(ans,query(1,1,n,id[x],id[y]));
return ans;
}
void updates(int x,int y,int c)
{
while(top[x]!=top[y])
{
if(depth[top[x]]<depth[top[y]]) swap(x,y);
update(1,1,n,id[top[x]],id[x],c);
x = fa[top[x]];
}
if(id[x]>id[y]) swap(x,y);
update(1,1,n,id[x],id[y],c);
}
/*namespace sgt
{
#define mid ((l+r)>>1)
#undef mid
}*/
/*int root[MAX_N],cnt,sz;
namespace hjt
{
#define mid ((l+r)>>1)
struct node{int l,r,maxx;}T[MAX_N*40];
#undef mid
}*/
int main()
{
//ios::sync_with_stdio(false);
//freopen("a.txt","r",stdin);
//freopen("b.txt","w",stdout);
int m,a,b,x,y;
n = read();m = read();
init();
for(int i = 1;i<n;++i)
{
a = read();b=read();
add(a,b);add(b,a);
}
build(1,1,n);
dfs1(1,0);
dfs2(1,1);
for(int i = 1;i<=m;++i)
{
a = read();b=read();x=read();y=read();
updates(a,b,1);
if(sum(x,y)==1) printf("Y\n");
else printf("N\n");
updates(a,b,0);
}
//fclose(stdin);
//fclose(stdout);
//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
return 0;
}
BZOJ3531
这个题也是十分的骚呢 首先十分好想到对每个宗教都维护一颗线段树 大胆的建树 也就100000棵树吧糟糕 MLE了 那么就上动态开点啊 反正他最多有100000个人
/*
if you can't see the repay
Why not just work step by step
rubbish is relaxed
to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod = (int)1e9+7;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];
inline int read()
{
int date = 0,m = 1; char ch = 0;
while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();
if(ch=='-'){m = -1; ch = getchar();}
while(ch>='0' && ch<='9')
{
date = date*10+ch-'0';
ch = getchar();
}return date*m;
}
int Max(int a,int b){return a>b?a:b;}
const int MAX_N = 100025;
const int N = 100000;
int p[MAX_N],now,eid,cnt,Rank[MAX_N],depth[MAX_N],top[MAX_N],id[MAX_N],belong[MAX_N],arr[MAX_N],sz[MAX_N],son[MAX_N],fa[MAX_N],root[MAX_N],maxx[MAX_N<<5],s[MAX_N<<5],lson[MAX_N<<5],rson[MAX_N<<5];
void init()
{
eid = 0;
memset(p,-1,sizeof(p));
}
struct edge
{
int v,next;
}e[MAX_N<<1];
void add(int u,int v)
{
e[eid].v = v;
e[eid].next = p[u];
p[u] = eid++;
}
void update(int &rt,int l,int r,int x,int v)
{
if(!rt)
{
rt = ++now;
maxx[rt] = s[rt] = v;
}
if(l==r)
{
maxx[rt] = v;
s[rt] = v;
return;
}
int mid = (l+r)>>1;
if(x<=mid) update(lson[rt],l,mid,x,v);
else update(rson[rt],mid+1,r,x,v);
maxx[rt] = Max(maxx[lson[rt]],maxx[rson[rt]]);
s[rt] = s[lson[rt]]+s[rson[rt]];
}
int query(int rt,int l,int r,int x,int y)
{
if(!rt) return 0;
if(x<=l&&r<=y)
{
return s[rt];
}
int mid = (l+r)>>1;
if(x>mid) return query(rson[rt],mid+1,r,x,y);
else if(y<=mid) return query(lson[rt],l,mid,x,y);
else return query(lson[rt],l,mid,x,y)+query(rson[rt],mid+1,r,x,y);
}
int Query(int rt,int l,int r,int x,int y)
{
if(!rt) return 0;
if(x<=l&&r<=y) return maxx[rt];
int mid = (l+r)>>1;
if(x>mid) return Query(rson[rt],mid+1,r,x,y);
else if(y<=mid) return Query(lson[rt],l,mid,x,y);
else return Max(Query(lson[rt],l,mid,x,y),Query(rson[rt],mid+1,r,x,y));
}
void dfs1(int x,int fath)
{
fa[x] = fath;
depth[x] = depth[fath]+1;
sz[x] = 1;
for(int i = p[x];i+1;i=e[i].next)
{
int v = e[i].v;
if(v==fath) continue;
dfs1(v,x);
sz[x]+=sz[v];
if(sz[son[x]]<sz[v]) son[x] = v;
}
}
void dfs2(int u,int t)
{
top[u] = t;
id[u] = ++cnt;
Rank[cnt] = u;
if(!son[u]) return;
dfs2(son[u],t);
for(int i = p[u];i+1;i=e[i].next)
{
int v= e[i].v;
if(v!=son[u]&&v!=fa[u]) dfs2(v,v);
}
}
int Sum(int x,int y,int rt)
{
int ans = 0;
while(top[x]!=top[y])
{
if(depth[top[x]]<depth[top[y]]) swap(x,y);
ans += query(rt,1,N,id[top[x]],id[x]);
x = fa[top[x]];
}
if(id[x]>id[y]) swap(x,y);
ans += query(rt,1,N,id[x],id[y]);
return ans;
}
int sum(int x,int y,int rt)
{
int ans = 0;
while(top[x]!=top[y])
{
if(depth[top[x]]<depth[top[y]]) swap(x,y);
ans = Max(ans,Query(rt,1,N,id[top[x]],id[x]));
x = fa[top[x]];
}
if(id[x]>id[y]) swap(x,y);
ans = Max(ans,Query(rt,1,N,id[x],id[y]));
return ans;
}
/*namespace sgt
{
#define mid ((l+r)>>1)
#undef mid
}*/
/*int root[MAX_N],cnt,sz;
namespace hjt
{
#define mid ((l+r)>>1)
struct node{int l,r,maxx;}T[MAX_N*40];
#undef mid
}*/
int main()
{
//ios::sync_with_stdio(false);
//freopen("a.txt","r",stdin);
//freopen("b.txt","w",stdout);
int n,m,a,b,x,y;
n = read();m = read();
char opt[5];
for(int i = 1;i<=n;++i){
arr[i] = read();belong[i] = read();
}
init();
for(int i = 1;i<n;++i)
{
a = read();b= read();
add(a,b);add(b,a);
}
dfs1(1,0);
dfs2(1,1);
for(int i = 1;i<=n;++i)
{
update(root[belong[i]],1,N,id[i],arr[i]);
}
for(int i = 1;i<=m;++i)
{
scanf("%s",opt);
x = read();y =read();
if(opt[0]=='Q')
{
if(opt[1]=='S')
{
printf("%d\n",Sum(x,y,root[belong[x]]));
}
else
{
printf("%d\n",sum(x,y,root[belong[x]]));
}
}
else
{
if(opt[1]=='C')
{
int last = belong[x];
update(root[last],1,N,id[x],0);
belong[x] = y;
update(root[y],1,N,id[x],arr[x]);
}
else
{
arr[x] = y;
update(root[belong[x]],1,N,id[x],y);
}
}
}
//fclose(stdin);
//fclose(stdout);
//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
return 0;
}
HDU6547
女生赛的题 写完队友问我有没有树链剖分板子 脸都没了 作为数据结构选手 西安E都不懂点和点之间的最短路是什么 队友这样问 小菜鸡决定好好学下树链剖分
这题能读题到码完提交AC仅用14分钟 希望今年区域赛小菜鸡也能这样
/*
if you can't see the repay
Why not just work step by step
rubbish is relaxed
to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod = (int)1e9+7;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];
inline int read()
{
int date = 0,m = 1; char ch = 0;
while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();
if(ch=='-'){m = -1; ch = getchar();}
while(ch>='0' && ch<='9')
{
date = date*10+ch-'0';
ch = getchar();
}return date*m;
}
const int MAX_N = 100025;
int n,p[MAX_N],eid,arr[MAX_N],cnt,top[MAX_N],Rank[MAX_N],id[MAX_N],sz[MAX_N],son[MAX_N],fa[MAX_N],depth[MAX_N],maxx[MAX_N<<2];
ll s[MAX_N<<2];
void init()
{
memset(p,-1,sizeof(p));
eid = 0;
}
struct edge
{
int v,next;
}e[MAX_N<<1];
void add(int u,int v)
{
e[eid].v = v;
e[eid].next = p[u];
p[u] = eid++;
}
int Max(int a,int b) {return a > b?a:b;}
void up(int rt)
{
s[rt] = s[rt<<1]+s[rt<<1|1];
maxx[rt] = Max(maxx[rt<<1],maxx[rt<<1|1]);
}
void build(int rt,int l,int r)
{
if(l==r)
{
maxx[rt] = s[rt] = arr[Rank[l]];
return ;
}
int mid =(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
up(rt);
}
void update(int rt,int l,int r,int x,int y)
{
if(maxx[rt]==1) return;
if(l==r) {maxx[rt] = sqrt(maxx[rt]);s[rt] = maxx[rt];return;}
int mid = (l+r)>>1;
if(x>mid) update(rt<<1|1,mid+1,r,x,y);
else if(y<=mid) update(rt<<1,l,mid,x,y);
else update(rt<<1,l,mid,x,y),update(rt<<1|1,mid+1,r,x,y);
up(rt);
}
ll query(int rt,int l,int r,int x,int y)
{
if(x<=l&&r<=y) return s[rt];
int mid = (l+r)>>1;
if(x>mid) return query(rt<<1|1,mid+1,r,x,y);
else if(y<=mid) return query(rt<<1,l,mid,x,y);
else return query(rt<<1,l,mid,x,y)+query(rt<<1|1,mid+1,r,x,y);
}
void dfs1(int x,int fath)
{
fa[x] = fath;
depth[x] = depth[fath]+1;
sz[x] = 1;
for(int i = p[x];i+1;i=e[i].next)
{
int v =e[i].v;
if(v==fath) continue;
dfs1(v,x);
sz[x]+=sz[v];
if(sz[son[x]]<sz[v]) son[x] = v;
}
}
void dfs2(int u,int t)
{
top[u] = t;
id[u] = ++cnt;
Rank[cnt ] = u;
if(!son[u]) return;
dfs2(son[u],t);
for(int i = p[u];i+1;i=e[i].next)
{
int v =e[i].v;
if(v!=son[u]&&v!=fa[u]) dfs2(v,v);
}
}
ll sum(int x,int y)
{
ll ans = 0;
while(top[x]!=top[y])
{
if(depth[top[x]]<depth[top[y]]) swap(x,y);
ans += query(1,1,n,id[top[x]],id[x]);
x = fa[top[x]];
}
if(id[x]>id[y]) swap(x,y);
ans+=query(1,1,n,id[x],id[y]);
return ans;
}
void updates(int x,int y)
{
while(top[x]!=top[y])
{
if(depth[top[x]]<depth[top[y]]) swap(x,y);
update(1,1,n,id[top[x]],id[x]);
x = fa[top[x]];
}
if(id[x]>id[y]) swap(x,y);
update(1,1,n,id[x],id[y]);
}
/*namespace sgt
{
#define mid ((l+r)>>1)
#undef mid
}*/
/*int root[MAX_N],cnt,sz;
namespace hjt
{
#define mid ((l+r)>>1)
struct node{int l,r,maxx;}T[MAX_N*40];
#undef mid
}*/
int main()
{
//ios::sync_with_stdio(false);
//freopen("a.txt","r",stdin);
//freopen("b.txt","w",stdout);
int a,b,m,opt,x,y;
n =read();m = read();
init();
for(int i = 1;i<=n;++i) arr[i] = read();
for(int i = 1;i<n;++i)
{
a = read();b = read();
add(a,b);add(b,a);
}
dfs1(1,0);
dfs2(1,1);
build(1,1,n);
for(int i = 1;i<=m;++i)
{
opt = read();x=read();y=read();
if(opt==0)
{
updates(x,y);
}
else
{
printf("%lld\n",sum(x,y));
}
}
//fclose(stdin);
//fclose(stdout);
//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
return 0;
}
西安邀请赛E
这道题线段树版本有道升级版本
FZU2105
然后小菜鸡ljq很容易就想到线段树怎么做
然后跟队友说 这题能出
等下 他问点和点之间的最短路
woc 点和点之间的最短路是什么啊 猝
…
拆位 维护区间1的个数 奇数表示存在 偶数表示不存在
/*
if you can't see the repay
Why not just work step by step
rubbish is relaxed
to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod = (int)1e9+7;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];
inline int read()
{
int date = 0,m = 1; char ch = 0;
while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();
if(ch=='-'){m = -1; ch = getchar();}
while(ch>='0' && ch<='9')
{
date = date*10+ch-'0';
ch = getchar();
}return date*m;
}
const int MAX_N = 100025;
int ans,n,p[MAX_N],eid,cnt,id[MAX_N],Rank[MAX_N],arr[MAX_N],sz[MAX_N],fa[MAX_N],son[MAX_N],s[MAX_N<<2][31],col[MAX_N<<2][31],depth[MAX_N],top[MAX_N];
void init()
{
eid = 0;
memset(p,-1,sizeof(p));
}
struct edge
{
int v,next;
}e[MAX_N<<1];
void add(int u,int v)
{
e[eid].v = v;
e[eid].next = p[u];
p[u] = eid++;
}
void up(int rt)
{
for(int i = 0;i<30;++i)
{
s[rt][i] = s[rt<<1][i] + s[rt<<1|1][i];
}
}
void build(int rt,int l,int r)
{
for(int i = 0;i<30;++i) col[rt][i] = -1;
if(l==r)
{
for(int i = 0;i<30;++i)
{
if((1<<i)&arr[Rank[l]]) s[rt][i] = 1;
else s[rt][i] = 0;
}
return ;
}
int mid = (l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
up(rt);
}
void down(int rt,int l,int r)
{
int mid = (l+r)>>1;
for(int i = 0;i<30;++i)
{
if(col[rt][i]!=-1)
{
col[rt<<1|1][i] = col[rt<<1][i] = col[rt][i];
if(col[rt][i]==1)
{
s[rt<<1][i] = mid-l+1;
s[rt<<1|1][i] = r-mid;
}
else
{
s[rt<<1][i] = 0;
s[rt<<1|1][i] = 0;
}
col[rt][i] = -1;
}
}
}
void update(int rt,int l,int r,int x,int y,int v,int flag)
{
if(x<=l&&r<=y)
{
if(flag==1)
{
for(int i = 0;i<30;++i)
{
if((1<<i)&v)
{
col[rt][i] = 1;
s[rt][i] = r-l+1;
}
}
}
else
{
for(int i = 0;i<30;++i)
{
if(!((1<<i)&v))
{
col[rt][i] = 0;
s[rt][i] = 0;
}
}
}
return;
}
down(rt,l,r);
int mid = (l+r)>>1;
if(x>mid) update(rt<<1|1,mid+1,r,x,y,v,flag);
else if(y<=mid) update(rt<<1,l,mid,x,y,v,flag);
else update(rt<<1,l,mid,x,y,v,flag),update(rt<<1|1,mid+1,r,x,y,v,flag);
up(rt);
}
void query(int rt,int l,int r,int x,int y)
{
if(x<=l&&r<=y)
{
for(int i = 0;i<30;++i)
{
if(s[rt][i]&1) ans^=(1<<i);
}
return;
}
down(rt,l,r);
int mid = (l+r)>>1;
if(x>mid) query(rt<<1|1,mid+1,r,x,y);
else if(y<=mid) query(rt<<1,l,mid,x,y);
else query(rt<<1,l,mid,x,y),query(rt<<1|1,mid+1,r,x,y);
}
void dfs1(int x,int fath)
{
fa[x] = fath;
depth[x] = depth[fath]+1;
sz[x] = 1;
for(int i = p[x];i+1;i=e[i].next)
{
int v = e[i].v;
if(v==fath) continue;
dfs1(v,x);
sz[x]+=sz[v];
if(sz[son[x]]<sz[v]) son[x] = v;
}
}
void dfs2(int u,int t)
{
top[u] = t;
id[u] = ++cnt;
Rank[cnt] = u;
if(!son[u]) return;
dfs2(son[u],t);
for(int i = p[u];i+1;i=e[i].next)
{
int v =e[i].v;
if(v!=son[u]&&v!=fa[u]) dfs2(v,v);
}
}
void sum(int x,int y)
{
while(top[x]!=top[y])
{
if(depth[top[x]]<depth[top[y]]) swap(x,y);
query(1,1,n,id[top[x]],id[x]);
x = fa[top[x]];
}
if(id[x]>id[y]) swap(x,y);
query(1,1,n,id[x],id[y]);
}
void updates(int x,int y,int c,int flag)
{
while(top[x]!=top[y])
{
if(depth[top[x]]<depth[top[y]]) swap(x,y);
update(1,1,n,id[top[x]],id[x],c,flag);
x = fa[top[x]];
}
if(id[x]>id[y]) swap(x,y);
update(1,1,n,id[x],id[y],c,flag);
}
/*namespace sgt
{
#define mid ((l+r)>>1)
#undef mid
}*/
/*int root[MAX_N],cnt,sz;
namespace hjt
{
#define mid ((l+r)>>1)
struct node{int l,r,maxx;}T[MAX_N*40];
#undef mid
}*/
int main()
{
//ios::sync_with_stdio(false);
//freopen("a.txt","r",stdin);
//freopen("b.txt","w",stdout);
int m,x,y,opt;
n = read();m = read();
for(int i = 1;i<=n;++i) arr[i] = read();
init();
for(int i = 1;i<n;++i)
{
x = read();y=read();
add(x,y);add(y,x);
}
dfs1(1,0);
dfs2(1,1);
build(1,1,n);
for(int i = 1;i<=n;++i)
{
opt = read();x=read();y=read();
if(opt==1)
{
updates(1,x,y,1);
}
else if(opt==2)
{
updates(1,x,y,2);
}
else
{
ans = 0;
sum(1,x);
if(ans!=y) printf("YES\n");
else printf("NO\n");
}
}
//fclose(stdin);
//fclose(stdout);
//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
return 0;
}