zoukankan      html  css  js  c++  java
  • 用堆操作不断加入点来找到每个点对应所包含的值的个数的理解

    首先还是要清楚一下堆操作的代码,毕竟线段树打多了,打堆的时候总会往线段树方向靠近

    首先是建堆:

    D=1;
    for(;D<maxn+2;D<<=1);

    然后给堆赋予值就可以了

    查找区间段的和:
    int query(int s,int t)
    {
        int i=D+s-1,j=D+t+1,ans=0;
        for(;i^j^1;i>>=1,j>>=1){
            if(~i&1) ans+=sum[i^1];
            if(j&1) ans+=sum[j^1];
        }
        return ans;
    }

    更新操作:

    void update(int i)
    {
        for(;i^1;i>>=1)
            sum[i>>1]=sum[i]+sum[i^1];
    }

    之前也做了一道star level的题写成了博客,这里继续来写一遍,就是问对于一个星星的位置,比其x小于等于和y小于等于的点有多少个

    这里我们所采取的是先进行一维上的排序,然后排好序后用另一维度来建树

    如星星的题目已经以y的大小先后排好序了,那我们就省事了

    我们从第一个节点不断添加进去,来找比它x小的数有几个,每次添加一个x,都要tree[D+x]++,再进行更新操作,因为后面的点是绝对不会影响到前面的点的

    所以是可以这样做的:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 #define N 32000
     6 int sum[N<<2],D;
     7 void push_up(int i)
     8 {
     9     for(;i^1;i>>=1)
    10         sum[i>>1]=sum[i]+sum[i^1];
    11 }
    12 int query(int s,int t)
    13 {
    14     int i=D+s-1,j=D+t+1,ans=0;
    15     for(;i^j^1;i>>=1,j>>=1)
    16     {
    17         if(~i&1) ans+=sum[i^1];
    18         if(j&1) ans+=sum[j^1];
    19     }
    20     return ans;
    21 }
    22 int main()
    23 {
    24     int n,a[15005],b[15005],ans[15005],maxn=0;
    25     scanf("%d",&n);
    26     for(int i=1;i<=n;i++){
    27         scanf("%d%d",&a[i],&b[i]);
    28         a[i]++;
    29         maxn=max(maxn,a[i]);
    30     }
    31     memset(sum,0,sizeof(sum));
    32     D=1;
    33     for(;D<maxn+2;D<<=1);
    34     for(int i=1;i<=n;i++){
    35         ans[i]=query(1,a[i]);
    36         sum[a[i]+D]++;
    37         //printf("%d,%d
    ",a[i],sum[a[i]+D]);
    38         push_up(a[i]+D);
    39     }
    40     int lev[15005];
    41     memset(lev,0,sizeof(lev));
    42     for(int i=1;i<=n;i++) lev[ans[i]]++;
    43     for(int i=0;i<n;i++) printf("%d
    ",lev[i]);
    44     return 0;
    45 }

    第二题:

    SPOJ RATING

    这道题目也是两个维度,不过如果出现一样的值的话,者之间是不算谁比谁大的,这是跟星星不一样的地方

    所以我们排好序后,每次添加点进入的时候还需要判断是否与前一个点值完全相同,如果相同不访问,直接继承前面一个点的值就可以了,然后再做更新

    同时星星的点是题目本身按顺序给出的,而这里是乱序的,我们需要事先排好序然后不断添入点

    我采取的方法是,建立结构体,除2维的数据外,还需记录id号,不然没法记录每个位置比别人大的个数

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 #define N 300005
     6 int sum[N<<2],D,maxn;
     7 struct Edge{
     8     int x,y,id;
     9     bool operator<(const Edge &m)const
    10     {
    11         return x==m.x?y<m.y:x<m.x;
    12     }
    13 }e[N];
    14 void update(int i)
    15 {
    16     for(;i^1;i>>=1)
    17         sum[i>>1]=sum[i]+sum[i^1];
    18 }
    19 int query(int s,int t)
    20 {
    21     int i=D+s-1,j=D+t+1,ans=0;
    22     for(;i^j^1;i>>=1,j>>=1){
    23         if(~i&1) ans+=sum[i^1];
    24         if(j&1) ans+=sum[j^1];
    25     }
    26     return ans;
    27 }
    28 int main()
    29 {
    30     int n,ans[N];
    31     maxn=0;
    32     memset(sum,0,sizeof(sum));
    33     scanf("%d",&n);
    34     for(int i=0;i<n;i++){
    35         scanf("%d%d",&e[i].x,&e[i].y);
    36         maxn=max(maxn,e[i].y);
    37         e[i].id=i;
    38     }
    39     D=1;
    40     for(;D<maxn+2;D<<=1);
    41     sort(e,e+n);
    42     int k;
    43     for(int i=0;i<n;i++){
    44         if(i>1&&e[i].x==e[i-1].x&&e[i].y==e[i-1].y){
    45         }
    46         else{
    47             k=query(1,e[i].y);
    48         }
    49         ans[e[i].id]=k;
    50         sum[D+e[i].y]++;
    51         update(D+e[i].y);
    52     }
    53     for(int i=0;i<n;i++)
    54         printf("%d
    ",ans[i]);
    55     return 0;
    56 }
  • 相关阅读:
    模拟登陆江西理工大学教务系统
    python3爬虫 -----华东交大校园新闻爬取与数据分析
    以selenium模拟登陆12306
    PAT (Basic Level) Practice (中文)1076 Wifi密码 (15 分)
    PAT (Basic Level) Practice (中文)1047 编程团体赛 (20 分)
    PAT (Basic Level) Practice (中文)1029 旧键盘 (20 分)
    PAT (Basic Level) Practice (中文)1016 部分A+B (15 分)
    PAT (Basic Level) Practice (中文)1031 查验身份证 (15 分)
    PAT (Basic Level) Practice (中文)1041 考试座位号 (15 分)
    PAT (Basic Level) Practice (中文)1037 在霍格沃茨找零钱 (20 分)
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/3901300.html
Copyright © 2011-2022 走看看