zoukankan      html  css  js  c++  java
  • HDU 4638 Group (线段树 + 离线)

    题意:给定一个N长的序列,有n个人编号1-n , 第i个人和第i-1,i+1 互相为朋友,询问多次,问你询问的区间里面有多少堆(可以互相认识)朋友:

    解题思路:开始一想有点像并查集的味道,不过想到LSS(我的队友,图论大牛)博客里面说的是线段树加离线(http://blog.csdn.net/u010126535),就按这个方面去想了,这题的主要思想是对询问的左端点按从大到小排序,然后对序列从后往前扫,对于A[I] 如果 A[I]- 1 或A[I] +1 出现过的话,更新其(它的两个邻居位置)线段树节点(+1);然后询问的答案就是这个区间长度-区间和,(这里主要是因为总是有一个连续序列排在最后面那个单独出来,我们就是求这个单独出来的个数,读者好好想想,我也是YY了好久。。)。

    解题代码:

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <iostream>
      4 #include <algorithm>
      5 #include <string>
      6 #include <math.h>
      7 
      8 using namespace std;
      9 
     10 #define maxn 100005
     11 struct op
     12 {
     13   int l , r ;
     14   int num;
     15 }ops[maxn];
     16 int hs[maxn];
     17 struct node
     18 {
     19   int l , r, m ;
     20   int num ;
     21 }tree[maxn*4];
     22 int L(int c)
     23 {
     24   return 2*c;
     25 }
     26 int R(int c)
     27 {
     28    return 2*c + 1;
     29 }
     30 void Pushup(int c)
     31 {
     32    tree[c].num = tree[L(c)].num + tree[R(c)].num;
     33 }
     34 void build(int c , int p , int v)
     35 {
     36     tree[c].l = p;
     37     tree[c].r = v ;
     38     tree[c].m = (p+v)/2;
     39     tree[c].num = 0 ;
     40     if(p == v)
     41         return ;
     42     build(L(c),p,tree[c].m);
     43     build(R(c),tree[c].m+1,v);
     44 }
     45 void update(int c ,int p  )
     46 {
     47     if(tree[c].l == tree[c].r && tree[c].l == p)
     48     {
     49         tree[c].num ++ ;
     50         return ;
     51     }
     52     if(p <= tree[c].m) update(L(c),p);
     53     else if(p > tree[c].m) update(R(c),p);
     54     Pushup(c);
     55 }
     56 int tsum = 0 ;
     57 void getsum(int c , int p ,int v )
     58 {
     59    if(p <= tree[c].l && v >= tree[c].r)
     60    {
     61      tsum += tree[c].num ;
     62      return ;
     63    }
     64    if(v <= tree[c].m) getsum(L(c),p,v);
     65    else if(p > tree[c].m) getsum(R(c),p,v);
     66    else {
     67     getsum(L(c),p,tree[c].m);
     68     getsum(R(c),tree[c].m+1 ,v);
     69    }
     70 }
     71 int a[maxn];
     72 int cmp(struct op a ,struct op b)
     73 {
     74      return a.l > b.l;
     75 }
     76 int ans[maxn];
     77 int main()
     78 {
     79     int t;
     80     scanf("%d",&t);
     81     while(t--)
     82     {
     83       memset(hs,0,sizeof(hs));
     84       int n ,m ;
     85       scanf("%d %d",&n,&m);
     86       build(1,1,n);
     87       for(int i = 1;i <= n;i ++)
     88         scanf("%d",&a[i]);
     89       for(int i = 1;i <= m;i ++ )
     90         {
     91           scanf("%d %d",&ops[i].l,&ops[i].r);
     92           ops[i].num = i ;
     93         }
     94       sort(ops+1,ops+1+m,cmp);
     95       int k = 1 ;
     96       for(int i = n; i >= 1 ;i --)
     97       {
     98           hs[a[i]] = i ;
     99           if(hs[a[i]-1] != 0 )
    100           {
    101              update(1,hs[a[i]-1]);
    102           }
    103           if(hs[a[i]+1] != 0 )
    104           {
    105              update(1,hs[a[i]+1]);
    106           }
    107 
    108 
    109           while(ops[k].l == i)
    110           {
    111             tsum = 0;
    112             getsum(1,ops[k].l,ops[k].r);
    113             ans[ops[k].num] =(ops[k].r - ops[k].l +1) -tsum;
    114             k++;
    115           }
    116       }
    117       for(int i= 1;i <= m;i ++)
    118         printf("%d
    ",ans[i]);
    119     }
    120 
    121   return 0 ;
    122 }
    View Code
    没有梦想,何谈远方
  • 相关阅读:
    .net验证是否合法邮箱和ip地址的方式
    .net通用类型转换方法
    asp.net中的<%%>的使用
    autofac初识
    .net面试题
    asp.net使用一般处理程序实现文件下载
    asp.net 一般处理程序接收上传文件的问题
    Python学习日记(十八) 序列化模块
    Python学习日记(十七) os模块和sys模块
    Python学习日记(十六) time模块和random模块
  • 原文地址:https://www.cnblogs.com/zyue/p/3246788.html
Copyright © 2011-2022 走看看