BZOJ1984月下“毛景樹”

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章