zoukankan      html  css  js  c++  java
  • hdu 4417(2012 杭州网络赛)

    唉,比赛的时候怎么都不会啊!!

    题解:http://blog.csdn.net/acm_cxlove/article/details/8014170

    划分树+二分答案:划分树可以方便的求解k-number。再利用二分答案,即区间内小于h的个数(最大为r-l+1,最小为0)。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 
      6 using namespace std;
      7 
      8 #define ls rt<<1
      9 #define rs rt<<1|1
     10 #define lson l,m,ls
     11 #define rson m+1,r,rs
     12 
     13 #define MAXN 100010
     14 
     15 struct Seg_Tree
     16 {
     17     int l,r;
     18 }tt[MAXN<<2];
     19 int len ,sorted[MAXN],toLeft[20][MAXN];
     20 int val[20][MAXN];
     21 
     22 void build(int d,int l,int r,int rt)
     23 {
     24     tt[rt].l=l;
     25     tt[rt].r=r;
     26     if(tt[rt].l == tt[rt].r) return ;
     27     int m=(l+r)>>1;
     28     int lsame = m-l+1;
     29     for(int i=l;i<=r;i++)
     30         if(val[d][i] < sorted[m])
     31             lsame--;
     32     int lpos =l,rpos=m+1,same=0;
     33     for(int i=l;i<=r;i++)
     34     {
     35         if(i==l)
     36             toLeft[d][i]=0;
     37         else
     38             toLeft[d][i] = toLeft[d][i-1];
     39         if(val[d][i] < sorted[m])
     40         {
     41             toLeft[d][i]++;
     42             val[d+1][lpos++] = val[d][i];
     43         }
     44         else if(val[d][i] > sorted[m])
     45             val[d+1][rpos++] = val[d][i];
     46         else
     47         {
     48             if(same<lsame)
     49             {
     50                 same++;
     51                 toLeft[d][i]++;
     52                 val[d+1][lpos++] = val[d][i];
     53             }
     54             else
     55                 val[d+1][rpos++] = val[d][i];
     56         }
     57     }
     58     build(d+1,lson);
     59     build(d+1,rson);
     60 }
     61 
     62 int query(int k,int d,int l,int r,int rt)
     63 {
     64     if(l==r) return val[d][l];
     65     int s,ss;
     66     if(l == tt[rt].l)
     67     {
     68         s = toLeft[d][r];
     69         ss=0;
     70     }
     71     else
     72     {
     73         s=toLeft[d][r] - toLeft[d][l-1];
     74         ss=toLeft[d][l-1];
     75     }
     76     if(s >= k)
     77     {
     78         int newl = tt[rt].l+ss;
     79         int newr = tt[rt].l+ss+s-1;
     80         return query(k,d+1,newl,newr,ls);
     81     }
     82     else
     83     {
     84         int m = (tt[rt].l + tt[rt].r)>>1;
     85         int bb = l-tt[rt].l -ss;
     86         int b= r-l+1-s;
     87         int newl = m+bb+1;
     88         int newr = m+bb +b;
     89         return query(k-s,d+1,newl,newr,rs);
     90     }
     91 }
     92 
     93 int bsearch(int r,int h,int L,int R)//r代表最多有多少个
     94 {
     95     int l =0;
     96     while(l<r)
     97     {
     98         int m = (l+r)>>1;//二分答案(个数)
     99         if(query(m,0,L,R,1) >h)
    100             r=m;
    101         else
    102             l=m+1;
    103     }
    104     return l;
    105 }
    106 
    107 int main()
    108 {
    109     int t,n,m;
    110     scanf("%d",&t);
    111     int cas=1;
    112     while(t--)
    113     {
    114         scanf("%d%d",&n,&m);
    115         for(int i=1;i<=n;i++)
    116         {
    117             scanf("%d",&val[0][i]);
    118             sorted[i]=val[0][i];
    119         }
    120         sort(sorted+1,sorted+n+1);
    121         build(0,1,n,1);
    122         printf("Case %d:\n",cas++);
    123         while(m--)
    124         {
    125             int l,r,h;
    126             scanf("%d%d%d",&l,&r,&h);
    127             if(query(1,0,l+1,r+1,1) > h)
    128                 puts("0");
    129             else if(query(r-l+1,0,l+1,r+1,1) <= h)
    130                 printf("%d\n",r-l+1);
    131             else
    132             {
    133                 int res = bsearch(r-l+1,h,l+1,r+1);
    134                 while(res != 0 && query(res,0,l+1,r+1,1) >h)
    135                     res--;
    136                 printf("%d\n",res);
    137             }
    138         }
    139     }
    140     return 0;
    141 }

    原来是将所有的询问读入,按H从小到大排序。然后对于所有的结点也按从小到大排序,然后根据查询的H,将比H小的点加入到线段树,然后就是一个很简单的区间和,,,,,做的题还是太少了。

    后来写的离线线段树:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cmath>
      5 #include <algorithm>
      6 
      7 using namespace std;
      8 
      9 #define mid (l+r)>>1
     10 #define ls rt<<1
     11 #define rs rt<<1|1
     12 #define lson l,m,rt<<1
     13 #define rson m+1,r,rt<<1|1
     14 
     15 #define MAXN 100010
     16 
     17 int sum[MAXN<<2],ans[MAXN];
     18 
     19 struct Que
     20 {
     21     int l,r,h,id;
     22 }Q[MAXN];
     23 struct node
     24 {
     25     int h,id;
     26 }in[MAXN];
     27 int n,m;
     28 bool cmp1(const Que &a,const Que &b)
     29 {
     30     return a.h<b.h;
     31 }
     32 bool cmp2(const node & a,const node &b)
     33 {
     34     return a.h<b.h;
     35 }
     36 void pushup(int rt)
     37 {
     38     sum[rt]=sum[ls]+sum[rs];
     39 }
     40 
     41 void build(int l,int r,int rt)
     42 {
     43     sum[rt]=0;
     44     if(l==r) return;
     45     int m = mid;
     46     build(lson);
     47     build(rson);
     48 }
     49 void update(int p,int q,int l,int r,int rt)
     50 {
     51     if(l==r)
     52     {
     53         sum[rt]+=q;
     54         return ;
     55     }
     56     int m=mid;
     57     if(p<=m) update(p,q,lson);
     58     else update(p,q,rson);
     59     pushup(rt);
     60 }
     61 int query(int L,int R,int l,int r,int rt)
     62 {
     63     if(L<=l && r<=R)
     64         return sum[rt];
     65     int m=mid;
     66     int ret=0;
     67     if(L<=m) ret+=query(L,R,lson);
     68     if(m<R) ret+=query(L,R,rson);
     69     return ret;
     70 }
     71 
     72 int main()
     73 {
     74     int t;
     75     scanf("%d",&t);
     76     int cas=1;
     77     while(t--)
     78     {
     79         scanf("%d%d",&n,&m);
     80         for(int i=0;i<n;i++)
     81         {
     82             scanf("%d",&in[i].h);
     83             in[i].id=i+1;
     84         }
     85         for(int i=0;i<m;i++)
     86         {
     87             scanf("%d%d%d",&Q[i].l,&Q[i].r,&Q[i].h);
     88             Q[i].id=i+1;
     89         }
     90         build(1,MAXN,1);
     91         sort(Q,Q+m,cmp1);
     92         sort(in,in+n,cmp2);
     93 
     94         int i=0,j=0;
     95         while(i<m)
     96         {
     97             while(in[j].h<=Q[i].h)
     98             {
     99                 update(in[j].id,1,1,MAXN,1);
    100                 j++;
    101             }
    102             ans[Q[i].id]=query(Q[i].l+1,Q[i].r+1,1,MAXN,1);
    103             i++;
    104         }
    105         printf("Case %d:\n",cas++);
    106         for(int i=1;i<=m;i++)
    107             printf("%d\n",ans[i]);
    108 
    109     }
    110     return 0;
    111 }
  • 相关阅读:
    敏捷结果30天之第十七天:找出高效时间,并利用它来处理重要事情
    每天一个linux命令(13):less 命令
    敏捷结果30天之第十九天:你在为谁做事
    每天一个linux命令(6):rmdir 命令
    每天一个linux命令(11):nl命令
    代码重构学习笔记三:重构72招式
    每天一个linux命令(4):mkdir命令
    敏捷结果30天之第二十二天:设计你的一天
    敏捷结果30天之第二十一天:正面失败,吸取教训,改善结果
    每天一个linux命令(8):cp 命令
  • 原文地址:https://www.cnblogs.com/Missa/p/2700676.html
Copyright © 2011-2022 走看看