您的位置:首页 > 其它

BZOJ1984月下“毛景树”

2016-03-25 20:49 405 查看
1984: 月下“毛景树”

Time Limit: 20 Sec Memory Limit: 64 MB

Submit: 1298 Solved: 411

Description

毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园。 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里。爬啊爬~爬啊爬毛毛虫爬到了一颗小小的“毛景树”下面,发现树上长着他最爱吃的毛毛果~ “毛景树”上有N个节点和N-1条树枝,但节点上是没有毛毛果的,毛毛果都是长在树枝上的。但是这棵“毛景树”有着神奇的魔力,他能改变树枝上毛毛果的个数:  Change k w:将第k条树枝上毛毛果的个数改变为w个。  Cover u v w:将节点u与节点v之间的树枝上毛毛果的个数都改变为w个。  Add u v w:将节点u与节点v之间的树枝上毛毛果的个数都增加w个。 由于毛毛虫很贪,于是他会有如下询问:  Max u v:询问节点u与节点v之间树枝上毛毛果个数最多有多少个。

Input

第一行一个正整数N。 接下来N-1行,每行三个正整数Ui,Vi和Wi,第i+1行描述第i条树枝。表示第i条树枝连接节点Ui和节点Vi,树枝上有Wi个毛毛果。 接下来是操作和询问,以“Stop”结束。

Output

对于毛毛虫的每个询问操作,输出一个答案。

Sample Input

4

1 2 8

1 3 7

3 4 9

Max 2 4

Cover 2 4 5

Add 1 4 10

Change 1 16

Max 2 4

Stop

Sample Output

9

16

【Data Range】

1<=N<=100,000,操作+询问数目不超过100,000。

保证在任意时刻,所有树枝上毛毛果的个数都不会超过10^9个。

下狠心写这道题。。

链剖一天搞定。。

把边权下放到深度较大的点。。

WA点:

①查询操作不能用lca

②标记之间有相互作用

③修改和查询的时候要左端点右移一位

手动测试数据:

Sample Input1

9

3 5 8

3 8 9

7 8 1

5 4 7

6 7 9

3 1 3

2 1 5

9 4 6

Change 1 7

Cover 9 4 26658

Change 7 6

Max 6 4

Max 4 8

Add 5 4 868

Cover 5 2 31875

Add 2 5 26600

Change 5 1

Stop

Sample Output1

9

9

Sample Input2

5

1 3 3

1 2 1

3 4 3

5 4 3

Cover 1 5 3

Add 3 2 3

Change 4 5

Change 1 4

Max 4 1

Change 1 1

Max 5 2

Stop

Sample Output2

4

5

Sample Input3

5

3 5 1

1 5 2

1 2 2

4 5 2

Change 3 5

Cover 5 2 28916

Max 2 5

Cover 4 1 365

Max 1 5

Add 5 3 29929

Add 4 3 21700

Change 4 3

Max 4 2

Stop

Sample Output3

28916

365

28916

一个不完美的对拍:

#include<cstdio>
#include<ctime>
#include<cstdlib>
using namespace std;
int main()
{
int i,x,y,z,n,w;
srand((int)time(0));
freopen("test1.in","w",stdout);
n=rand()%10;
printf("%d\n",n);
for (i=1;i<n;i++)
{
x=rand()%n+1,y=rand()%n+1,z=rand()%n+1;
printf("%d %d %d\n",x,y,z);
}
for (i=1;i<=10;i++)
{
x=rand();
y=rand(),z=rand();
if (x%5==1) printf("Max %d %d\n",y%n+1,z%n+1);
if (x%5==2) w=rand(),printf("Cover %d %d %d\n",y%n+1,z%n+1,w);
if (x%5==3) w=rand(),printf("Add %d %d %d\n",y%n+1,z%n+1,w);
if (x%5==4) printf("Change %d %d\n",y%n+1,z%n+1);
}
printf("Stop");
return 0;
}


附上本蒟蒻的代码:

#include<cstdio>
#include<iostream>
#include<climits>
#include<cstring>
using namespace std;
#define MAXN 100001
int n,cnt,sz,h[MAXN],father[MAXN][17],pos[MAXN],belong[MAXN],size[MAXN],deep[MAXN],delta1[MAXN<<2],delta2[MAXN<<2];
bool vis[MAXN];
struct data
{
int to,next;
}edge[MAXN<<1];
struct kx
{
int value;
}node[MAXN<<2];
struct forever
{
int start,end,val,point;
}a[MAXN];

int read()
{
int w=0,c=1; char ch=getchar();
while (ch<'0' || ch>'9')
{
if (ch=='-') c=-1;
ch=getchar();
}
while (ch>='0' && ch<='9')
w=w*10+ch-'0',ch=getchar();
return w*c;
}

void add(int u,int v)
{
cnt++,edge[cnt].next=h[u],h[u]=cnt,edge[cnt].to=v;
cnt++,edge[cnt].next=h[v],h[v]=cnt,edge[cnt].to=u;
}

void dfs1(int x)
{
int i;
size[x]=1,vis[x]=true;
for (i=1;i<=16;i++)
{
if (deep[x]<(1<<i)) break;
father[x][i]=father[father[x][i-1]][i-1];
}
for (i=h[x];i;i=edge[i].next)
{
if (vis[edge[i].to]) continue;
deep[edge[i].to]=deep[x]+1,father[edge[i].to][0]=x;
dfs1(edge[i].to),size[x]+=size[edge[i].to];
}
}

void dfs2(int x,int chain)
{
int k=0,i;
pos[x]=++sz,belong[x]=chain;
for (i=h[x];i;i=edge[i].next)
if (deep[edge[i].to]>deep[x] && size[edge[i].to]>size[k])
k=edge[i].to;
if (!k) return;
dfs2(k,chain);
for (i=h[x];i;i=edge[i].next)
if (deep[edge[i].to]>deep[x] && k!=edge[i].to)
dfs2(edge[i].to,edge[i].to);
}

void update(int s)
{
node[s].value=max(node[s*2].value,node[s*2+1].value);
}

void build(int s,int l,int r)
{
if (l==r) return;
build(s*2,l,(l+r)/2),build(s*2+1,(l+r)/2+1,r);
}

void pushdown(int s,int l,int r)
{
int mid=(l+r)/2;
if (l==r) return;
if (delta1[s]!=-1)
{
delta2[s*2]=delta2[s*2+1]=0,delta1[s*2]=delta1[s*2+1]=delta1[s];
node[s*2].value=node[s*2+1].value=delta1[s],delta1[s]=-1;
}
if (delta2[s])
{
node[s*2].value+=delta2[s],node[s*2+1].value+=delta2[s];
if (delta1[s*2]!=-1) delta1[s*2]+=delta2[s];
else delta2[s*2]+=delta2[s];
if (delta1[s*2+1]!=-1) delta1[s*2+1]+=delta2[s];
else delta2[s*2+1]+=delta2[s];
delta2[s]=0;
}
}

void change(int s,int l,int r,int x,int y)
{
pushdown(s,l,r);
int mid=(l+r)/2;
if (l==x && l==r)
{
node[s].value=y;
return;
}
if (x<=mid) change(s*2,l,mid,x,y);
else change(s*2+1,mid+1,r,x,y);
update(s);
}

int querymax(int s,int l,int r,int x,int y)
{
int mid=(l+r)/2,ans;
pushdown(s,l,r);
if (x>y) return -INT_MAX;
if (x<=l && y>=r) return node[s].value;
if (x<=mid) ans=querymax(s*2,l,mid,x,y);
else ans=-INT_MAX;
if (y>mid) ans=max(ans,querymax(s*2+1,mid+1,r,x,y));
update(s);
return ans;
}

int solvemax(int x,int y)
{
int mx=-INT_MAX;
for (;belong[x]!=belong[y];x=father[belong[x]][0])
{
if (deep[belong[x]]<deep[belong[y]]) swap(x,y);
mx=max(mx,querymax(1,1,n,pos[belong[x]],pos[x]));
}
if (deep[x]<deep[y]) swap(x,y);
mx=max(mx,querymax(1,1,n,pos[y]+1,pos[x]));
return mx;
}

void insert1(int s,int l,int r,int x,int y,int z)
{
pushdown(s,l,r);
int mid=(l+r)/2;
if (x<=l && y>=r)
{
node[s].value=delta1[s]=z;
return;
}
if (x<=mid) insert1(s*2,l,mid,x,y,z);
if (y>mid) insert1(s*2+1,mid+1,r,x,y,z);
update(s);
}

void solveinsert1(int x,int y,int z)
{
for (;belong[x]!=belong[y];x=father[belong[x]][0])
{
if (deep[belong[x]]<deep[belong[y]]) swap(x,y);
insert1(1,1,n,pos[belong[x]],pos[x],z);
}
if (deep[x]<deep[y]) swap(x,y);
insert1(1,1,n,pos[y]+1,pos[x],z);
}

void insert2(int s,int l,int r,int x,int y,int z)
{
pushdown(s,l,r);
int mid=(l+r)/2;
if (x<=l && y>=r)
{
node[s].value+=z,delta2[s]=z;
return;
}
if (x<=mid) insert2(s*2,l,mid,x,y,z);
if (y>mid) insert2(s*2+1,mid+1,r,x,y,z);
update(s);
}

void solveinsert2(int x,int y,int z)
{
for (;belong[x]!=belong[y];x=father[belong[x]][0])
{
if (deep[belong[x]]<deep[belong[y]]) swap(x,y);
insert2(1,1,n,pos[belong[x]],pos[x],z);
}
if (deep[x]<deep[y]) swap(x,y);
insert2(1,1,n,pos[y]+1,pos[x],z);
}

int main()
{
/*freopen("test1.in","r",stdin);
freopen("test1.out","w",stdout);*/
memset(delta1,-1,sizeof(delta1));
int i,x,y,z,t;
char s[10];
n=read();
for (i=1;i<n;i++) a[i].start=read(),a[i].end=read(),a[i].val=read(),add(a[i].start,a[i].end);
dfs1(1),dfs2(1,1),build(1,1,n);
/*for (i=1;i<=n;i++) printf("%d ",deep[i]);
printf("\n");*/
for (i=1;i<n;i++)
if (deep[a[i].start]>deep[a[i].end]) a[i].point=a[i].start;
else a[i].point=a[i].end;
for (i=1;i<n;i++) change(1,1,n,pos[a[i].point],a[i].val);
while (scanf("%s",&s))
{
if (s[1]=='t') break;
x=read(),y=read();
if (s[1]=='a') printf("%d\n",solvemax(x,y));
if (s[1]=='o') z=read(),solveinsert1(x,y,z);
if (s[1]=='d') z=read(),solveinsert2(x,y,z);
if (s[1]=='h') change(1,1,n,pos[a[x].point],y);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: