zoukankan      html  css  js  c++  java
  • 二维线段树(hdu1823)

    二维线段树其实也没有其他新知识,从名字上也能看出,他不过就是将一维变成二维,把之前的一维线段树每个节点再扩展成一棵线段树如下图:

    图上红标号点是一维树,蓝标号点就是二维树。

    从图也可看出,我们之所以要用二维线段树是因为你要得到的答案限制条件用一维无法控制,而二维线段树可以在满足一维线段树条件的情况下在二维还可以有给我们限制条件的空间,最终就可以从一维到二维再到答案。

    图看起来比一维线段树多了好多分支,但是对他进行操作时其实和一维的没什么两样,就是在满足一维条件情况下对二维进行操作。

    看代码你就知道了(代码是我在知道二维线段树的大概思路后自己写的,可能比较丑,不过题目都ac了,应该没有错,建议大家自己先写实现一遍)

    hdu1823:http://acm.hdu.edu.cn/showproblem.php?pid=1823

    中文题,题意就不说了

    思路就是线段树一维存身高,二维存活跃度和缘分,将一位小数乘10化为整数。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<queue>
      4 #include<algorithm>
      5 #include<string>
      6 #include<string.h>
      7 #include<map>
      8 #include<vector>
      9 #include<cmath>
     10 #include<iterator>
     11 #define mem(a,b) memset(a,b,sizeof(a))
     12 #define MOD 100000007
     13 #define LL long long
     14 #define INF 0x3f3f3f3f
     15 const double pi = acos(-1.0);
     16 const int Maxn=101;
     17 using namespace std;
     18 struct Tree{//二维树 
     19     int l,r;
     20     int mh;
     21 };
     22 struct Mtree{//一维树 
     23     int l,r;
     24     struct Tree tree[Maxn*4*10];
     25 }mt[Maxn*4];
     26 void Btree(int mk,int k,int l,int r){//二维树的建树操作 
     27     mt[mk].tree[k].l=l,mt[mk].tree[k].r=r;
     28     if(l==r){
     29         mt[mk].tree[k].mh=-1;
     30         return ;
     31     }
     32     int mid=(l+r)>>1;
     33     Btree(mk,k<<1,l,mid);
     34     Btree(mk,k<<1|1,mid+1,r);
     35     mt[mk].tree[k].mh=max(mt[mk].tree[k<<1].mh,mt[mk].tree[k<<1|1].mh);
     36 }
     37 void BMtree(int k,int l,int r){//一维树的建树操作 
     38     mt[k].l=l,mt[k].r=r;
     39     Btree(k,1,0,1000);//这里就是从一维节点对二维树进行建立 
     40     if(l==r){
     41         return ;
     42     }
     43     int mid=(l+r)>>1;
     44     BMtree(k<<1,l,mid);
     45     BMtree(k<<1|1,mid+1,r);
     46 }
     47 void addP_tree(int mk,int k,int A,int L){//二维树的节点更新 
     48     if(mt[mk].tree[k].l==mt[mk].tree[k].r&&mt[mk].tree[k].l==A){
     49         mt[mk].tree[k].mh=max(L,mt[mk].tree[k].mh);//不能覆盖,可能会有输入的出缘分值其他都相同的情况 
     50         return ;
     51     }
     52     int mid=(mt[mk].tree[k].l+mt[mk].tree[k].r)>>1;
     53     if(mid>=A){
     54         addP_tree(mk,k<<1,A,L);
     55     }else{
     56         addP_tree(mk,k<<1|1,A,L);
     57     }
     58     mt[mk].tree[k].mh=max(mt[mk].tree[k<<1].mh,mt[mk].tree[k<<1|1].mh);
     59 }
     60 void addP_mt(int k,int H,int A,int L){//从一维树找到符合条件的节点,再进去对二维树进行更新 
     61     if(mt[k].l==mt[k].r&&mt[k].l==H){
     62         addP_tree(k,1,A,L);//二维更新 
     63         return ;
     64     }    
     65     int mid=(mt[k].l+mt[k].r)>>1;
     66     if(mid>=H){
     67         addP_mt(k<<1,H,A,L); 
     68     }else{
     69         addP_mt(k<<1|1,H,A,L);
     70     }
     71     addP_tree(k,1,A,L);//回溯时对该点相关父点更新 
     72 }
     73 int ans;
     74 void query_tree(int mk,int k,int al,int ar){//查询 
     75     if(mt[mk].tree[k].l>=al&&mt[mk].tree[k].r<=ar){
     76         ans=max(mt[mk].tree[k].mh,ans);
     77         return ;
     78     }
     79     int mid=(mt[mk].tree[k].l+mt[mk].tree[k].r)>>1;
     80     if(ar<=mid){
     81         query_tree(mk,k<<1,al,ar);
     82     }else if(al>mid){
     83         query_tree(mk,k<<1|1,al,ar);
     84     }else{
     85         query_tree(mk,k<<1,al,ar);
     86         query_tree(mk,k<<1|1,al,ar);
     87     }
     88 }
     89 void query_mt(int k,int hl,int hr,int al,int ar){
     90     if(mt[k].l>=hl&&mt[k].r<=hr){
     91         query_tree(k,1,al,ar);//子树询问
     92         return ; 
     93     }
     94     int mid=(mt[k].l+mt[k].r)>>1;
     95     if(hr<=mid){
     96         query_mt(k<<1,hl,hr,al,ar);
     97     }else if(mid<hl){
     98         query_mt(k<<1|1,hl,hr,al,ar);
     99     }else{
    100         query_mt(k<<1,hl,hr,al,ar);
    101         query_mt(k<<1|1,hl,hr,al,ar);
    102     }
    103 }
    104 int main(){
    105     int n;
    106     char s[5];
    107     int H,H1,H2;
    108     double A,L,A1,A2;
    109     while(~scanf("%d",&n)&&n){
    110         mem(mt,0);
    111         BMtree(1,100,200);
    112         while(n--){
    113             scanf("%s",s);
    114             if(s[0]=='I'){
    115                 scanf("%d%lf%lf",&H,&A,&L);
    116                 addP_mt(1,H,(int)(A*10),(int)(L*10));
    117             }else if(s[0]=='Q'){
    118                 scanf("%d%d%lf%lf",&H1,&H2,&A1,&A2);
    119                 ans=-1;
    120                 query_mt(1,min(H1,H2),max(H1,H2),min((int)(A1*10),(int)(A2*10)),max((int)(A1*10),(int)(A2*10)));//这是这题目中的一个坑,注意!!!! 
    121                 if(ans!=-1)
    122                 printf("%.1lf
    ",(double)(ans*1.0/10));
    123                 else
    124                 printf("-1
    ");
    125             }
    126         }
    127     }
    128     return 0;
    129 }
    View Code

    二维线段树的空间复杂度一看就高了很多,所以题目一般数据都不是特大

    有错请指正。

  • 相关阅读:
    python快捷键的使用【摘抄】
    Jmeter5.1 Plugins Manager配置dummy使用jp@gc
    jmeter正则中常见的转义字符-笔记三
    测试人员问问题的技巧是什么?
    一个简单的python实现百度登录操作
    2.3 Go内置函数
    2.2 Go变量类型
    2.1Go语言特性
    1.2Go环境搭建之Mac
    1.1Go环境搭建之Linux
  • 原文地址:https://www.cnblogs.com/liuzuolin/p/10548855.html
Copyright © 2011-2022 走看看