zoukankan      html  css  js  c++  java
  • 清点人数

    清点人数(jdoj1427-vijos1320)

        题目大意:n个点,k个事件。每个事件为A , B , C。A表示查询该点的前缀和,B点是该点加权值,C点是该点减权值。

        注释:n<=500000,k<=100000,至少有30000个A

          想法:显然,单点修改,区间查询,数据范围较大,想到用一个较强的数据架构——线段树维护。而今天,我们来介绍一种特殊的数据结构——树状数组。

            接下来,我们来介绍树状数组的性质即特性。我们想线段树一样来理解树状数组。我们用 a[ ]来记录一段区间,A[]表示单点的权值。我们用一种特殊的想法——a[1]=A[1],a[2] = A [ 1 ] + A [ 2 ],a[3]=A[3] , a[4]=a[2]+a[3]+A[4].....那么,我们再次介绍一种位运算——lowbit,表示一个数的二进制表示中从末位开始的第一个非零数的位置的值,lowbit返回一个二的r次方 , r 便是那个值。由这个东西,我们就构架出整个树状数组的体系——一切的修改之间的差值为上一个值的lowbit,而lowbit可以简单的推出,为t&(-t),即,它表示的就是按位,取反,加一的全过程。这样,查询啊,修改啊什么的就全部可以在O(logn)的时间复杂度内实现。那么,我们发现,可以用树状数组实现的,线段树都可以做到,但,为什么我们仍然如此推崇树状数组?原因十分简单,好写!太jb好写了。比那个什么线段树的代码量小到不知道哪里去了。所以在此,极其推荐树状数组,而且比较好理解。

          我们回归这道题,我们想,每次单点修改,只会对后面产生贡献,所以,我们就可以对其后面的shu进行lowbit差值的修改,注意数据量,细心即可。

        最后,附上丑陋的代码......

     1 #include <iostream>
     2 #include <cstdio>
     3 using namespace std;
     4 int n;
     5 char a[5];
     6 int tree[500001];
     7 int lowbit(int t)
     8 {
     9     return t&(-t);
    10 }
    11 void add(int x,int y)
    12 {
    13     for(int i=x;i<=n;i+=lowbit(i))
    14     {
    15         tree[i]+=y;
    16     }
    17 }
    18 void query(int x)
    19 {
    20     int ans=0;
    21     for(int i=x;i;i-=lowbit(i))
    22     {
    23         ans+=tree[i];
    24     }
    25     printf("%d
    ",ans);
    26 }
    27 int main()
    28 {
    29     int m;
    30     int x,y;
    31     scanf("%d%d",&n,&m);
    32     for(int i=1;i<=m;i++)
    33     {
    34         scanf("%s",a+1);
    35         if(a[1]=='A')
    36         {
    37             scanf("%d",&x);
    38             query(x);
    39         }
    40         else if(a[1]=='B')
    41         {
    42             scanf("%d%d",&x,&y);
    43             add(x,y);
    44         }
    45         else
    46         {
    47             scanf("%d%d",&x,&y);
    48             add(x,-y);
    49         }
    50     }
    51     return 0;
    52 }

        小结:错误

            1.记住,这时一个教训:lowbit函数完全可以写在for循环里面,没有必要单独列出,导致效率变低。

            2.printf与%c千万别在一起使!!

        转载请注明:http://www.cnblogs.com/ShuraK/p/7856899.html 

    | 欢迎来原网站坐坐! >原文链接<

  • 相关阅读:
    shell 调试
    shell中的函数参数
    shell脚本执行的区别
    《C# 语言学习笔记》——C# 简介
    【SVN】SVN使用教程总结
    SVN Unable to connect to a repository at URL问题解决
    前后端分离(三)
    前后端分离(二)
    前后端分离(一)
    【git】Git的使用
  • 原文地址:https://www.cnblogs.com/ShuraK/p/7856899.html
Copyright © 2011-2022 走看看