zoukankan      html  css  js  c++  java
  • HDU 4638 Group 树状数组 + 思路

    实际上就是问这个区间编号连续的段的个数,假如一个编号连续的段有(a+b)个人,我把他们分在同一组能得到的分值为(a+b)^2,而把他们分成人数为a和b的两组的话,得到的分值就是a^2+b^2,显然(a+b)^2 > a^2+b^2,所以对于每个区间,尽可能把他们分成尽量少的组。

    考虑把这些数从后往前添加,每添加一个数num[i],如果num[i]+1或者num[i]-1有且只有一个已经存在,则段数不变;如果num[i]+1和num[i]-1同时存在,则段数-1,如果都不在,则段数+1。

    对于每个数num[i],我们记录把它添加进去的时候,它对段数产生的影响为c[i]( 即插入num[i]时对区间[i, N]的段数产生的影响 ),查询就是求c[i]的区间和。

    对于询问我们做离线处理,把每个询问按右端点从大到小排序,从后往前扫描,每次把询问右端点之外的数删掉,根据其是否会产生影响对c[i]进行更新。

    Sum( Query[i].r ) - Sum( Query[i].l - 1 ) 即为答案。

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <cstdlib>
      4 #include <algorithm>
      5 
      6 using namespace std;
      7 
      8 const int MAXN = 100010;
      9 
     10 struct node
     11 {
     12     int l, r, id;
     13 };
     14 
     15 int N, Q;
     16 node qry[MAXN];  //查询
     17 int C[MAXN];     //树状数组
     18 int num[MAXN];   //原数组
     19 int addr[MAXN];  //每个数在哪个位置
     20 int ans[MAXN];   //记录答案
     21 bool use[MAXN];  //该数是否存在
     22 
     23 bool cmp( node a, node b )
     24 {
     25     return a.r > b.r;
     26 }
     27 
     28 int lowbit( int x )
     29 {
     30     return x & (-x);
     31 }
     32 
     33 int Query( int x )
     34 {
     35     int res = 0;
     36     while ( x > 0 )
     37     {
     38         res += C[x];
     39         x -= lowbit(x);
     40     }
     41     return res;
     42 }
     43 
     44 void Update( int x, int val )
     45 {
     46     while ( x <= N )
     47     {
     48         C[x] += val;
     49         x += lowbit(x);
     50     }
     51     return;
     52 }
     53 
     54 void init()
     55 {
     56     memset( C, 0, sizeof(C) );
     57     memset( use, false, sizeof(use) );
     58 
     59     for ( int i = N; i > 0; --i )
     60     {
     61         if ( use[ num[i] - 1 ] && use[ num[i] + 1 ] )
     62         {
     63             Update( i, -1 );
     64         }
     65         else if ( !( use[ num[i] - 1 ] || use[ num[i] + 1 ] ) )
     66         {
     67             Update( i, 1 );
     68         }
     69         use[ num[i] ] = true;
     70     }
     71     return;
     72 }
     73 
     74 void solved()
     75 {
     76     int j = N;
     77     for ( int i = 0; i < Q; ++i )
     78     {
     79         while ( j > 0 && j > qry[i].r )
     80         {
     81             if ( num[j] > 1 && addr[ num[j] - 1 ] < j )
     82             {
     83                 Update( addr[ num[j] - 1 ], 1 );
     84             }
     85             if ( num[j] < N && addr[ num[j] + 1 ] < j )
     86             {
     87                 Update( addr[ num[j] + 1 ], 1 );
     88             }
     89             --j;
     90         }
     91         ans[ qry[i].id ] = Query( qry[i].r ) - Query( qry[i].l - 1 );
     92     }
     93 
     94     for ( int i = 0; i < Q; ++i )
     95         printf( "%d
    ", ans[i] );
     96 
     97     return;
     98 }
     99 
    100 int main()
    101 {
    102     int T;
    103     scanf( "%d", &T );
    104     while ( T-- )
    105     {
    106         scanf( "%d%d", &N, &Q );
    107         for ( int i = 1; i <= N; ++i )
    108         {
    109             scanf( "%d", &num[i] );
    110             addr[ num[i] ] = i;
    111         }
    112         for ( int i = 0; i < Q; ++i )
    113         {
    114             scanf("%d%d", &qry[i].l, &qry[i].r );
    115             qry[i].id = i;
    116         }
    117         sort( qry, qry + Q, cmp );
    118 
    119         init();
    120         solved();
    121     }
    122     return 0;
    123 }
  • 相关阅读:
    jQuery实现动态搜索显示功能
    面试
    Struts1和Struts2的区别和对比(完整版)
    JAVA调用增删改的存储过程
    Spring MVC入门
    jQuery Ajax通用js封装
    js ==与===区别
    shell脚本awk
    C++对象模型初窥
    再见,2021
  • 原文地址:https://www.cnblogs.com/GBRgbr/p/3233497.html
Copyright © 2011-2022 走看看