文件統計 [數據結構]
題目描述
“星農”是一個追求效率的公司,公司內的文件管理系統也不例外。現有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
加油!!