Aragorn’s Story HDU - 3966
题目链接
https://vjudge.net/problem/HDU-3966
题目思路
模板题
ac代码
const int maxn = 5e4+10;
const int inf = 1e9+10;
const ll llinf =1e18+10;
const ll mod = 1e9+7;
const double pi = acos(-1);
int n,m,p;
vector<int>vec[maxn];
int a[maxn];
char str[10];
int dep[maxn],siz[maxn],f[maxn],son[maxn],top[maxn],pos[maxn],in[maxn],cnt;
int t[maxn<<4],lz[maxn<<4];
void dfs1(int x,int fa)
{
dep[x]=dep[fa]+1;
f[x]=fa;
siz[x]=1;
int maxsize=-1;
for(auto to:vec[x])
{
if(to==fa)continue;
dfs1(to,x);
siz[x]+=siz[to];
if(siz[to]>maxsize)
{
son[x]=to;
maxsize=siz[to];
}
}
}
void dfs2(int x,int t)
{
in[x]=++cnt;
pos[cnt]=x;
top[x]=t;
if(son[x]==0)return;
dfs2(son[x],t);
for(auto to:vec[x])
{
if(to==f[x]||to==son[x])continue;
dfs2(to,to);
}
}
void pushup(int rt)
{
t[rt]=t[lson]+t[rson];
}
void pushdown(int rt,int l,int r)
{
if(lz[rt])
{
int mid=(l+r)>>1;
t[lson]+=lz[rt]*(mid-l+1);
t[rson]+=lz[rt]*(r-mid);
lz[lson]+=lz[rt];
lz[rson]+=lz[rt];
lz[rt]=0;
}
}
void build(int rt,int l,int r)
{
lz[rt]=0;
if(l==r)
{
t[rt]=a[pos[l]];
return;
}
int mid=(l+r)>>1;
build(lson,l,mid);
build(rson,mid+1,r);
pushup(rt);
}
void update(int rt,int l,int r,int L,int R,int k)
{
if(L<=l&&r<=R)
{
t[rt]+=k*(r-l+1);
lz[rt]+=k;
return;
}
int mid=(l+r)>>1;
pushdown(rt,l,r);
if(L<=mid)
update(lson,l,mid,L,R,k);
if(R>mid)
update(rson,mid+1,r,L,R,k);
pushup(rt);
}
int query(int rt,int l,int r,int L,int R)
{
if(L<=l&&r<=R)
{
return t[rt];
}
int mid=(l+r)>>1;
pushdown(rt,l,r);
int ans=0;
if(L<=mid)
ans+=query(lson,l,mid,L,R);
if(R>mid)
ans+=query(rson,mid+1,r,L,R);
return ans;
}
void updrange(int x,int y,int k)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
update(1,1,n,in[top[x]],in[x],k);
x=f[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
update(1,1,n,in[x],in[y],k);
}
signed main()
{
while(~scanf("%d%d%d",&n,&m,&p))
{
cnt=0;
for(int i=1;i<=n;i++)son[i]=0,vec[i].clear();
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1,u,v;i<=m;i++)
{
scanf("%d%d",&u,&v);
vec[u].push_back(v);
vec[v].push_back(u);
}
dfs1(1,1);
dfs2(1,1);
build(1,1,n);
while(p--)
{
int x,y,z;
scanf("%s",str);
if(str[0]=='Q')
{
scanf("%d",&x);
printf("%d\n",query(1,1,n,in[x],in[x]));
}else
{
scanf("%d%d%d",&x,&y,&z);
if(str[0]=='I')
updrange(x,y,z);
else
updrange(x,y,-z);
}
}
}
}
Housewife Wind POJ - 2763
题目链接
https://vjudge.net/problem/POJ-2763
题目思路
将边的值赋给深度大的端点后,就是一个模板题了。
因为我们求得是边的和,并且我们是向下赋值,所以查询的时候要注意不要多算边。
poj好多东西都不能用,做题体验蛮差的(小声bb)
ac代码
const int maxn = 3e5+10;
const int inf = 1e9+10;
const ll llinf =1e18+10;
const ll mod = 1e9+7;
int n,m,s;
int a[maxn];
pii e[maxn];
char str[10];
int dep[maxn],siz[maxn],f[maxn],son[maxn],top[maxn],pos[maxn],in[maxn],cnt,tot;
int t[maxn<<4],lz[maxn<<4];
int first[maxn];
struct node
{
int to,next,w;
}E[maxn];
void add(int u,int v,int w)
{
E[++tot].to=v;
E[tot].next=first[u];
E[tot].w=w;
first[u]=tot;
}
void dfs1(int x,int fa)
{
dep[x]=dep[fa]+1;
f[x]=fa;
siz[x]=1;
int maxsize=-1;
for(int i=first[x];i;i=E[i].next)
{
int to=E[i].to;
if(to==fa)continue;
a[to]=E[i].w;
dfs1(to,x);
siz[x]+=siz[to];
if(siz[to]>maxsize)
{
son[x]=to;
maxsize=siz[to];
}
}
}
void dfs2(int x,int t)
{
in[x]=++cnt;
pos[cnt]=x;
top[x]=t;
if(son[x]==0)return;
dfs2(son[x],t);
for(int i=first[x];i;i=E[i].next)
{
int to=E[i].to;
if(to==f[x]||to==son[x])continue;
dfs2(to,to);
}
}
void pushup(int rt)
{
t[rt]=t[lson]+t[rson];
}
void pushdown(int rt,int l,int r)
{
if(lz[rt])
{
int mid=(l+r)>>1;
t[lson]+=lz[rt]*(mid-l+1);
t[rson]+=lz[rt]*(r-mid);
lz[lson]+=lz[rt];
lz[rson]+=lz[rt];
lz[rt]=0;
}
}
void build(int rt,int l,int r)
{
lz[rt]=0;
if(l==r)
{
t[rt]=a[pos[l]];
return;
}
int mid=(l+r)>>1;
build(lson,l,mid);
build(rson,mid+1,r);
pushup(rt);
}
void update(int rt,int l,int r,int L,int R,int k)
{
if(L<=l&&r<=R)
{
t[rt]=k*(r-l+1);
lz[rt]=k;
return;
}
int mid=(l+r)>>1;
pushdown(rt,l,r);
if(L<=mid)
update(lson,l,mid,L,R,k);
if(R>mid)
update(rson,mid+1,r,L,R,k);
pushup(rt);
}
int query(int rt,int l,int r,int L,int R)
{
if(L<=l&&r<=R)
{
return t[rt];
}
int mid=(l+r)>>1;
pushdown(rt,l,r);
int ans=0;
if(L<=mid)
ans+=query(lson,l,mid,L,R);
if(R>mid)
ans+=query(rson,mid+1,r,L,R);
return ans;
}
int qyrange(int x,int y)
{
int ans=0;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
ans+=query(1,1,n,in[top[x]],in[x]);//这里我们后面会直接跳到top[x]的父亲节点,所以不用加一
x=f[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
ans+=query(1,1,n,in[x]+1,in[y]);//不加一会多计算一条边的权值
return ans;
}
signed main()
{
while(~scanf("%d%d%d",&n,&m,&s))
{
cnt=0;
for(int i=1;i<=n;i++)son[i]=0,first[i];
for(int i=1,u,v,w;i<=n-1;i++)
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
e[i].fi=u,e[i].se=v;
}
dfs1(1,1);
dfs2(1,1);
build(1,1,n);
while(m--)
{
int x,y,z;
scanf("%d%d",&x,&y);
if(x==0)
{
printf("%d\n",qyrange(s,y));
s=y;
}else
{
scanf("%d",&z);
int l=e[y].fi,r=e[y].se;
if(dep[l]>dep[r])
update(1,1,n,in[l],in[l],z);
else
update(1,1,n,in[r],in[r],z);
}
}
}
}
Tree POJ - 3237
题目链接
https://vjudge.net/problem/POJ-3237
题目思路
查询和修改边的值跟上题写法一样。
主要看取反的操作。
我们对于一组数全部乘上-1,不难发现这组数中最大值会变得最小,最小值会变得最大。
那么我们用线段树维护一个区间的最大值和最小值,每次取反操作把最大值最小值乘上-1后交换最大最小值就好了。
需要注意的是因为有负数,所以查询的时候统计答案的变量不能初始化为0,找了半个多小时的bug。。。
ac代码
const int maxn = 3e5+10;
const int inf = 1e9+10;
const ll llinf =1e18+10;
const ll mod = 1e9+7;
int n,m,s;
int a[maxn];
pii e[maxn];
char str[10];
int dep[maxn],siz[maxn],f[maxn],son[maxn],top[maxn],pos[maxn],in[maxn],cnt,tot;
pii t[maxn<<4];
int lz[maxn<<4];
int first[maxn];
struct node
{
int to,next,w;
}E[maxn];
void add(int u,int v,int w)
{
E[++tot].to=v;
E[tot].next=first[u];
E[tot].w=w;
first[u]=tot;
}
void dfs1(int x,int fa)
{
dep[x]=dep[fa]+1;
f[x]=fa;
siz[x]=1;
int maxsize=-1;
for(int i=first[x];i;i=E[i].next)
{
int to=E[i].to;
if(to==fa)continue;
a[to]=E[i].w;
dfs1(to,x);
siz[x]+=siz[to];
if(siz[to]>maxsize)
{
son[x]=to;
maxsize=siz[to];
}
}
}
void dfs2(int x,int t)
{
in[x]=++cnt;
pos[cnt]=x;
top[x]=t;
if(son[x]==0)return;
dfs2(son[x],t);
for(int i=first[x];i;i=E[i].next)
{
int to=E[i].to;
if(to==f[x]||to==son[x])continue;
dfs2(to,to);
}
}
void pushup(int rt)
{
t[rt].fi=max(t[lson].fi,t[rson].fi);
t[rt].se=min(t[lson].se,t[rson].se);
}
void pushdown(int rt)
{
if(lz[rt]<0)
{
t[lson].fi*=lz[rt];
t[rson].fi*=lz[rt];
t[lson].se*=lz[rt];
t[rson].se*=lz[rt];
swap(t[lson].fi,t[lson].se);
swap(t[rson].fi,t[rson].se);
lz[lson]*=lz[rt];
lz[rson]*=lz[rt];
lz[rt]=1;
}
}
void build(int rt,int l,int r)
{
lz[rt]=1;
if(l==r)
{
t[rt].fi=a[pos[l]];
t[rt].se=a[pos[l]];
return;
}
int mid=(l+r)>>1;
build(lson,l,mid);
build(rson,mid+1,r);
pushup(rt);
}
void update(int rt,int l,int r,int L,int R,int k)
{
if(L<=l&&r<=R)
{
t[rt].fi*=k;
t[rt].se*=k;
swap(t[rt].fi,t[rt].se);
lz[rt]*=k;
return;
}
int mid=(l+r)>>1;
pushdown(rt);
if(L<=mid)
update(lson,l,mid,L,R,k);
if(R>mid)
update(rson,mid+1,r,L,R,k);
pushup(rt);
}
int query(int rt,int l,int r,int L,int R)
{
if(L<=l&&r<=R)
{
return t[rt].fi;
}
int mid=(l+r)>>1;
pushdown(rt);
int ans=-inf;
if(L<=mid)
ans=max(ans,query(lson,l,mid,L,R));
if(R>mid)
ans=max(ans,query(rson,mid+1,r,L,R));
return ans;
}
int qyrange(int x,int y)
{
int ans=-inf;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
ans=max(ans,query(1,1,n,in[top[x]],in[x]));
x=f[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
ans=max(ans,query(1,1,n,in[x]+1,in[y]));
return ans;
}
void updrange(int x,int y,int k)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
update(1,1,n,in[top[x]],in[x],k);
x=f[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
update(1,1,n,in[x]+1,in[y],k);
}
void change(int rt,int l,int r,int p,int v)
{
if(l==r)
{
t[rt].fi=v;
t[rt].se=v;
return;
}
int mid=(l+r)>>1;
pushdown(rt);
if(mid>=p)
change(lson,l,mid,p,v);
else
change(rson,mid+1,r,p,v);
pushup(rt);
}
signed main()
{
int _;
scanf("%d",&_);
while(_--)
{
scanf("%d",&n);
cnt=0,tot=0;
for(int i=1;i<=n;i++)son[i]=0,first[i]=0;
for(int i=1,u,v,w;i<=n-1;i++)
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
e[i].fi=u,e[i].se=v;
}
dfs1(1,1);
dfs2(1,1);
a[1]=-inf;
build(1,1,n);
while(scanf("%s",str))
{
if(str[0]=='D')break;
int x,y;
scanf("%d%d",&x,&y);
if(str[0]=='Q')
{
printf("%d\n",qyrange(x,y));
}
if(str[0]=='C')
{
int l=e[x].fi,r=e[x].se;
if(dep[l]<dep[r])swap(l,r);
change(1,1,n,in[l],y);
}
if(str[0]=='N')
{
updrange(x,y,-1);
}
}
}
}
Aladdin and the Return Journey LightOJ - 1348
题目链接
https://vjudge.net/problem/LightOJ-1348
题目思路
模板题
Query on a tree SPOJ - QTREE
题目链接
https://vjudge.net/problem/SPOJ-QTREE
题目思路
比POJ - 3237少了取反操作,输入输出都一样,交同一份代码就能过。。。