zoukankan      html  css  js  c++  java
  • HDU4638

      1 /*树状数组求和,一边询问一边维护,离线处理*/
      2 #include<stdio.h>
      3 #include<algorithm>
      4 #include<string.h>
      5 using namespace std;
      6 const int maxn=100000+10;
      7 struct point
      8 {
      9     int l,r,index;
     10 }node[maxn];
     11 int a[maxn];
     12 int num[maxn];
     13 int index[maxn];
     14 int result[maxn];
     15 int n,m;
     16 bool cmp(const point a,const point b)
     17 {
     18     return a.l<b.l;
     19 }
     20 int lowbit(int x)
     21 {
     22     return x&(-x);
     23 }
     24 void updata(int x,int v)//修改
     25 {
     26     while(x<=n)
     27     {
     28        a[x]=a[x]+v;
     29        x=x+lowbit(x);//在修改的时候往右往上爬
     30     }
     31 }
     32 int sum(int x)//求和
     33 {
     34     int ans=0;
     35     while(x>0)
     36     {
     37         ans=ans+a[x];
     38         x=x-lowbit(x);//求和的时候,往左往上爬
     39     }
     40     return ans;
     41 }
     42 int main()
     43 {
     44     int i,j;
     45     int t;
     46     scanf("%d",&t);
     47     while(t--)
     48     {
     49         scanf("%d%d",&n,&m);
     50         for(i=1;i<=n;i++)
     51         {
     52             scanf("%d",&num[i]);
     53             index[num[i]]=i;
     54         }
     55         memset(a,0,sizeof(a));
     56         index[0]=n+10; index[n+1]=n+10;//边界处理
     57         for(i=1;i<=n;i++)
     58         {
     59             if(i<index[num[i]-1] && i<index[num[i]+1])//说明新插入的a[i],前面还没有和他构成连续的数,那么插入a[i]必然是段数增加1
     60                 updata(i,1);
     61             else if(i>index[num[i]-1] && i>index[num[i]+1])//说明新插入的a[i],前面有和他构成连续的数,因为以前a[i]-1和a[i]+1这些已经加了1,所以减去1,是使得这三个数的段贡献是1
     62                 updata(i,-1);
     63         }
     64          for(i=0;i<m;i++)//离线处理
     65          {
     66              scanf("%d%d",&node[i].l,&node[i].r);
     67              node[i].index=i;
     68          }
     69          sort(node,node+m,cmp);//按查询的左区间从小到大排
     70          i=1;
     71          j=0;
     72          while(j<m)//一边询问一边修改
     73          {
     74              while(i<=n && node[j].l>i)//因为每个节点i都属于一个人以它自身结尾的水平长条这样区间询问求和的时候会加上一些多余的数,所以要处理
     75              {
     76                  if(i>index[num[i]-1] && i>index[num[i]+1])//将包含i的节点删去1个段,因为i你不在询问区间内
     77                      updata(i,-1);
     78                  else if(i<index[num[i]-1] && i<index[num[i]+1])//不包含i的在询问的时候肯定段数加1
     79                  {
     80                      updata(i,-1);
     81                      updata(index[num[i]-1],1);
     82                      updata(index[num[i]+1],1);
     83                  }
     84                  else if(i<index[num[i]-1])
     85                  {
     86                      updata(i,-1);
     87                      updata(index[num[i]-1],1);
     88                  }
     89                  else if(i<index[num[i]+1])
     90                  {
     91                      updata(i,-1);
     92                      updata(index[num[i]+1],1);
     93                  }
     94                 i++;
     95              }
     96              while(j<m && node[j].l<=i)//处理起点相同的询问
     97              {
     98                  result[node[j].index]=sum(node[j].r);
     99                  j++;
    100              }
    101          }
    102          for(i=0;i<m;i++)
    103          {
    104              printf("%d
    ",result[i]);
    105          }
    106     }
    107     return 0;
    108 }
  • 相关阅读:
    【转帖】Explorer参数详解
    获取html页面时如何选择合适的Encoding
    不要在wpf窗口类的构造函数中抛异常
    把FlvDownloader重构了一下
    VK Cup 2012 Qualification Round 1 A. Next Round
    迎接2012新赛季——HDOJ系列热身赛(2) Problem A HDU 4161 Iterated Difference
    青蛙过河~~~~
    VK Cup 2012 Qualification Round 1 D. Ice Sculptures
    HDU 1006 Tick and Tick
    ACM参赛总结
  • 原文地址:https://www.cnblogs.com/okboy/p/3231970.html
Copyright © 2011-2022 走看看