文件统计 [数据结构]
题目描述
“星农”是一个追求效率的公司,公司内的文件管理系统也不例外。现有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
加油!!