HPU 1458 (數狀數組,利用的很神奇)

文件統計 [數據結構]

題目描述

“星農”是一個追求效率的公司,公司內的文件管理系統也不例外。現有n個文件夾分別命名爲1,2,3…n,它們構成一個文件目錄,1作爲此文件目錄的根目錄,其它文件夾均爲1號目錄的直接子目錄或間接子目錄。每個目錄裏初始時沒有任何文件。

現在有三種操作:

1.add x y –> 向x號目錄裏添加y個文件

2.delete x y –> 向x號目錄裏刪除y個文件,如果目錄中文件數不足y,則輸出”error”,不刪除文件並結束本次操作。

3.query x –> 查詢從x號文件夾到根目錄(1號文件夾),其文件個數之和。

輸入

第一行輸入一個整數T,表示有T組數據。

T組數據中,第一行輸入兩個整數n、m,表示有n個目錄和m次操作。

接下來n-1行,每行輸入兩個整數x、y,表示x和y互爲父子目錄。

然後m行表示m次操作,輸入方式見樣例及題目描述。

1 ≤ T ≤ 20

1 ≤ n,m,x,y ≤ 23333

輸出

對於delete操作,若x號目錄文件個數不足y個,則輸出”error”(不加雙引號);

對於query操作,輸出一個整數表示要查詢信息。

樣例輸入

1
5 5
1 2
2 4
2 5
1 3
add 5 2
query 2
delete 3 1
add 1 5
query 5

樣例輸出

0
error
7

地址:http://acm.hpu.edu.cn/problem.php?id=1458

這道題剛開始我一看就知道是線段樹和樹狀數組能解決的,但是自己一直想不懂怎麼用
MY 一直想分層 每次只要算上一層的加上自己這層的,一直超時,看了題解後發現了一個大坑 接下來n-1行,每行輸入兩個整數x、y,表示x和y互爲父子目錄。就是標紅的這一句,他只說明了是父子關係而並沒有說明誰是父誰是子,後來研究了一會發現我的思路也有問題,當分支多時會出bug 如果一個文件夾的父文件夾那一級有多個,就會出錯!!!

正確思路 :題解思路!!
先看圖
圖片有點大
就例如這個 先用dfs跑一邊 以那個順序作爲樹狀數組 dj1(圖上爲up) 代表進入文件夾的時間 dj2(圖上爲down)是出文件夾的時間.看添加,例如在二號文件夾添加文件 那麼受到影響的就是 2 4 5 6 2 那麼如何讓後面的不搜影響呢 所以就要在 dj1的位置加上文件數 而在dj2處減去文件數,這樣受到影響的就只有他們中間的了,另外開個數組存下每個文件夾裏的文件數,方便del

由於改了多次有點亂,先湊活吧

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rd(a) scanf("%d",&a)
#define rl(a) scanf("%lld",&a)
#define inf 0x3f3f3f3f
ll sum[56667];
int  dj1[23337];
int dj2[23337];
ll  vis[23337];
int o;
struct node
{

    int v,next;

} ss[46679];
int head[23338];
inline void tre_add(int u,int v)
{

    ss[o].next=head[u];
    ss[o].v=v;
    head[u]=o++;


}
void add(int x,int val,int n)
{

    while(x<=n)
    {

        sum[x]+=val;
        x+=x&-x;

    }


}
ll query(int x)
{

    ll ans=0;
    while(x>0)
    {

        ans+=sum[x];
        x-=x&-x;
    }
    return ans;


}
int v[23399];
int cnt;
void dfs(int ii)
{

    dj1[ii]=cnt++;
    for(int i=head[ii]; ~i; i=ss[i].next)
    {

        if(!v[ss[i].v])
        {
        v[ss[i].v]=1;
        dfs(ss[i].v);
        }

    }
    dj2[ii]=cnt++;

}

int main()
{
    //freopen("in.txt", "r", stdin);
    int t;
    rd(t);

    while(t--)
    {
        o=0;cnt=1;
        memset(v,0,sizeof(v));
        memset(vis,0,sizeof(vis));
        memset(sum,0,sizeof(sum));
        memset(head,-1,sizeof(head));
        int n,m;
        rd(n),rd(m);
        for(int i=1; i<n; i++)
        {
            int a,b;
            rd(a);
            rd(b);
            tre_add(a,b);
            tre_add(b,a);

        }
        v[1]=1;
        dfs(1);
        for(int i=0; i<m; i++)
        {

            char s[30];
            int a,b;
            scanf("%s",s);
            if(s[0]=='a')
            {
                rd(a);
                rd(b);
                add(dj1[a],b,2*n);
                add(dj2[a],-b,2*n);
                vis[a]+=b;

            }
            else if(s[0]=='q')
            {

                rd(a);
                ll k=query(dj1[a]);
                printf("%lld\n",k);

            }
            else
            {

                rd(a);
                rd(b);
                if(vis[a]<b)
                {


                    puts("error");


                }
                else
                {

                    vis[a]-=b;
                    add(dj1[a],-b,2*n);
                    add(dj2[a],b,2*n);
                }

            }


        }



    }






    return 0;
}

官方題解 :http://acm.hpu.edu.cn/showsource.php?id=74552

加油!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章