zoukankan      html  css  js  c++  java
  • 8月8号的线段树:HDU 1754&&POJ 3264&&HDU1166

    很明显,没有A一道题,题目意思很容易懂,但是就是shit的超时!!

    之后就崩溃了。

    晚上好像弄懂了线段树,先上题目:

                                                  I Hate It HDU 1754

    要用线段树才不会超时:

    (计算机运行数目达到10^8就要1S了!!而一般题目就是那么2000MS~5000MS)

     1 #include<iostream>
     2 #include<stdio.h>
     3 #include<algorithm>
     4 using namespace std;
     5 int a[200005];
     6 struct line
     7 {
     8     int left;
     9     int right;
    10     int max1;
    11 }node[200005*20];
    12 void build(int left,int right,int root)
    13 {
    14     node[root].left=left;
    15     node[root].right=right;
    16     if(left==right)
    17     {
    18         node[root].max1=a[left];
    19     }
    20     else
    21     {
    22         build(left,(left+right)/2,2*root);
    23         build((left+right)/2+1,right,2*root+1);
    24         node[root].max1=max(node[2*root].max1,node[2*root+1].max1);
    25     }
    26 }
    27 int find1(int left1,int right1,int root)
    28 {
    29     if(node[root].left>right1||node[root].right<left1)
    30         return 0;
    31     if(left1<=node[root].left&&right1>=node[root].right)
    32         return node[root].max1;
    33     int a,b;
    34     a=find1(left1,right1,2*root);
    35     b=find1(left1,right1,2*root+1);
    36     return max(a,b);
    37 }
    38 int update(int x,int y,int root)
    39 {
    40     if(x<node[root].left||x>node[root].right)
    41         return 0;
    42     if(node[root].left==x&&node[root].right==x)
    43     return node[root].max1=y;
    44     node[root].max1=max(update(x,y,2*root),update(x,y,2*root+1));
    45     return node[root].max1;
    46 }//这里不仅把自己的值更新,而且把改变之后每个根节点的最大值也进行了更新!
    47 int main()
    48 {
    49     int i,n,m,a1,a2;
    50     char b[2];
    51     while(scanf("%d%d",&n,&m)!=EOF)
    52     {
    53         for(i=1;i<=n;i++)
    54             scanf("%d",&a[i]);
    55         build(1,n,1);
    56         while(m--)
    57         {
    58             scanf("%s%d%d",b,&a1,&a2);
    59             if(b[0]=='Q')
    60                 printf("%d
    ",find1(a1,a2,1));
    61             else
    62             {
    63                 a[a1]=a2;
    64                 update(a1,a2,1);
    65             }
    66         }
    67     }
    68     return 0;
    69 }

    第一次看懂:首先题目数据的默认顺序应该是1,2,3,4...(不然那个线段树怎么判断找哪个点到哪个点)

    还有根节点,左节点,右节点的求法确定(即树的大体样子要清楚)

    找东西的话(题目从线段数要求解的),得从根节点往下找起!

    以根节点为依据,看他们的左右孩子和问题的关系。(包围还是半包围)

                                         Balanced Lineup  POJ 3264

    上面一个题的变行:这里不要update.

     1 #include<iostream>
     2 #include<stdio.h>
     3 #include<algorithm>
     4 using namespace std;
     5 int a[50005];
     6 int MaxNum,MinNum;
     7 struct line
     8 {
     9     int left;
    10     int right;
    11     int max1;
    12     int min1;
    13 }node[50005*20];
    14 void build(int left,int right,int root)
    15 {
    16     node[root].left=left;
    17     node[root].right=right;
    18     if(left==right)
    19     {
    20         node[root].max1=a[left];
    21         node[root].min1=a[right];
    22     }
    23     else
    24     {
    25         build(left,(left+right)/2,root*2);
    26         build((left+right)/2+1,right,2*root+1);
    27         node[root].max1=max(node[root*2].max1,node[root*2+1].max1);
    28         node[root].min1=min(node[root*2].min1,node[root*2+1].min1);
    29     }
    30 }
    31 int find1(int left1,int right1,int root)
    32 {
    33     if(left1>node[root].right||right1<node[root].left)
    34         return 0;
    35     if(left1<=node[root].left&&right1>=node[root].right)
    36     {
    37             MaxNum=max(node[root].max1,MaxNum);
    38             MinNum=min(node[root].min1,MinNum);
    39             return (MaxNum-MinNum);
    40     }
    41     int a,b;
    42     a=find1(left1,right1,2*root);
    43     b=find1(left1,right1,2*root+1);
    44     return max(a,b);
    45 }
    46 int main()
    47 {
    48     int n,m,i,a1,a2;
    49     while(scanf("%d%d",&n,&m)!=EOF)
    50     {
    51         for(i=1;i<=n;i++)
    52             scanf("%d",&a[i]);
    53         build(1,n,1);
    54         while(m--)
    55         {
    56             scanf("%d%d",&a1,&a2);
    57             MaxNum = -99999999;
    58             MinNum = 99999999;
    59             printf("%d
    ",find1(a1,a2,1));
    60         }
    61     }
    62     return 0;
    63 }

     为什么上面的第一题不用开个MaxNum来求最大值,而后面的题目要开个MaxNum,MinNum来求最大值和最小值?

    那是因为第一题只要求最大值,而第二题那最大值和最小值可能不在同一if判断语句中啊!!!!!

    (貌似这个问题只有我才会犯的吧,主要是第二题的代码直接是第一题的克隆体,才会那么在意那些不同之处!)

                                  敌兵布阵 HDU1166

    加深对线段树的理解:(首先明确一旦建立好线段树,那么就不会有重叠和交叉)

     1 #include<iostream>
     2 #include<stdio.h>
     3 #include<algorithm>
     4 using namespace std;
     5 int a[50005],ans;
     6 struct line
     7 {
     8     int left;
     9     int right;
    10     int sum;
    11 }node[50005*20];
    12 void build(int left,int right,int root)
    13 {
    14     node[root].left=left;
    15     node[root].right=right;
    16     if(left==right)
    17         node[root].sum=a[left];
    18     else
    19     {
    20         build(left,(left+right)/2,2*root);
    21         build((left+right)/2+1,right,2*root+1);
    22         node[root].sum=node[root*2].sum+node[root*2+1].sum;
    23     }
    24 }
    25 void query(int left1,int right1,int root)
    26 {
    27     if(left1>node[root].right||right1<node[root].left)
    28         return ;
    29     if(left1<=node[root].left&&right1>=node[root].right)
    30          ans+=node[root].sum;
    31     else
    32     {
    33         query(left1,right1,2*root);
    34         query(left1,right1,2*root+1);
    35     }
    36 }
    37 void insert1(int x,int y,int root)
    38 {
    39     if(x<node[root].left||x>node[root].right)
    40         return ;
    41     if(x>=node[root].left&&x<=node[root].right)
    42          node[root].sum+=y;
    43     insert1(x,y,2*root);
    44     insert1(x,y,2*root+1);
    45 }
    46 int main()
    47 {
    48     int d=0,t,n,i,a1,a2;
    49     char b[8];
    50     scanf("%d",&t);
    51     while(t--)
    52     {
    53         scanf("%d",&n);
    54         for(i=1;i<=n;i++)
    55             scanf("%d",&a[i]);
    56         build(1,n,1);
    57         printf("Case %d:
    ",++d);
    58         while(scanf("%s",b)!=EOF)
    59         {
    60             if(b[0]=='E')
    61                 break;
    62             scanf("%d%d",&a1,&a2);
    63             if(b[0]=='Q')
    64             {
    65                 ans=0;
    66                 query(a1,a2,1);
    67                 printf("%d
    ",ans);
    68             }
    69             else if(b[0]=='A')
    70                 insert1(a1,a2,1);
    71             else
    72                 insert1(a1,-a2,1);
    73       }
    74     }
    75     return 0;
    76 }
  • 相关阅读:
    eclipse常用的快捷键
    如何保留小数点后N位?
    EditText设置/隐藏光标位置、选中文本和获取/清除焦点(转)
    java.lang.RuntimeException: Unable to instantiate activity ComponentInfo异常(转)
    STL优先队列 hdu1896
    工作排序问题 poj2376
    STL存储邻接表
    二叉树的遍历
    快速排序
    并查集 并查集来判断是否存在环路
  • 原文地址:https://www.cnblogs.com/tt123/p/3246925.html
Copyright © 2011-2022 走看看