HPU 1458 (数状数组,利用的很神奇)

来源:互联网 发布:杭州投融界网络靠谱吗 编辑:程序博客网 时间:2024/05/21 06:11

文件统计 [数据结构]

题目描述

“星农”是一个追求效率的公司,公司内的文件管理系统也不例外。现有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 0x3f3f3f3fll 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

加油!!

原创粉丝点击