程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> HDU 4902 Nice boat 2014杭電多校訓練賽第四場F題(線段樹區間更新)

HDU 4902 Nice boat 2014杭電多校訓練賽第四場F題(線段樹區間更新)

編輯:C++入門知識

HDU 4902 Nice boat 2014杭電多校訓練賽第四場F題(線段樹區間更新)


解題報告:輸入一個序列,然後有q次操作,操作有兩種,第一種是把區間 (l,r) 變成x,第二種是把區間 (l,r) 中大於x的數跟 x 做gcd操作。   線段樹區間更新的題目,每個節點保存一個最大和最小值,當該節點的最大值和最小值相等的時候表示這個區間所有的數字都是相同的,可以直接對這個區間進行1或2操作,   進行1操作時,當還沒有到達要操作的區間但已經出現了節點的最大值跟最小值相等的情況時,說明這個區間的值都是相同的,但現在我只要在這個區間的一部分進行1操作,所以   我要先把這個節點的最大的最小值往下壓,直到找到了要操作的區間。   進行2操作時,如果該區間的最大值都小於x,則可以直接退出,如果最大值大於x,則表示這個區間可以進行gcd操作,然後繼續往下,直到找到最大值跟最小值相等的區間才開始   進行gcd操作,進行gcd操作之後不要忘了更新父節點的最大最小值。     復制代碼   1 #include<cstdio>   2 #include<cstring>   3 #include<iostream>   4 #include<algorithm>   5 using namespace std;   6 #define maxn 100005   7 struct node   8 {   9     int Max,Min,l,r;  10 }tree[4*maxn];  11 void build(int p)  12 {  13     if(tree[p].l == tree[p].r) return ;  14     int mid = (tree[p].l + tree[p].r) / 2;  15     tree[2*p].Max = tree[2*p+1].Max = -1;  16     tree[2*p].Min = tree[2*p+1].Min = 0x7fffffff;  17     tree[2*p].l = tree[p].l;  18     tree[2*p].r = mid;  19     tree[2*p+1].l = mid + 1;  20     tree[2*p+1].r = tree[p].r;  21     build(2*p);  22     build(2*p+1);  23 }  24 void push(int p,int l,int d)  25 {  26     tree[p].Max = max(tree[p].Max,d);  27     tree[p].Min = min(tree[p].Min,d);  28     if(tree[p].l == tree[p].r) return ;  29     int mid = (tree[p].l + tree[p].r) / 2;  30     if(l <= mid) push(2*p,l,d);  31     else push(2*p+1,l,d);  32 }  33 int gcd(int a,int b)  34 {  35     return b == 0? a : gcd(b,a%b);  36 }  37 void oper1(int p,int l,int r,int x)  38 {  39     if(tree[p].l == l && tree[p].r == r)  40     {  41         tree[p].Max = tree[p].Min = x;  42         return ;  43     }  44     int mid = (tree[p].l + tree[p].r) / 2;  45     if(tree[p].Max == tree[p].Min)  46     {  47         oper1(2*p+1,mid+1,tree[p].r,tree[p].Max);  //先把當前區間的值往下壓  48         oper1(2*p,tree[p].l,mid,tree[p].Max);  49     }  50     tree[p].Max = max(tree[p].Max,x);  51     tree[p].Min = min(tree[p].Min,x);  52     if(r <= mid)  53     oper1(2*p,l,r,x);  54     else if(l <= mid && r > mid)  55     {  56         oper1(2*p,l,mid,x);  57         oper1(2*p+1,mid+1,r,x);  58     }  59     else oper1(2*p+1,l,r,x);  60 }  61 void oper2(int p,int l,int r,int x)  62 {  63     int  mid = (tree[p].l + tree[p].r) / 2;  64     if(tree[p].l == l && tree[p].r == r)  65     {  66         if(tree[p].Max < x) return ;   //最大的都不可以進行gcd操作,直接退出   67         if(tree[p].Max == tree[p].Min)   //找到了值都相同的區間,可以直接進行gcd操作   68         {  69             if(tree[p].Max > x) tree[p].Max = tree[p].Min = gcd(tree[p].Max,x);  70             return ;  71         }  72         else if(tree[p].Max > x)  73         {  74             oper2(2*p,l,mid,x);  75             oper2(2*p+1,mid+1,r,x);  76         }  77         return ;  78     }  79     if(tree[p].Max == tree[p].Min)     //還沒找到操作的區間之前碰到了這個,則也要通過1操作,把這個節點的值往下壓   80     {  81         oper1(2*p,tree[p].l,mid,tree[p].Max);  82         oper1(2*p+1,mid+1,tree[p].r,tree[p].Max);  83     }  84     if(r <= mid)  85     oper2(2*p,l,r,x);  86     else if(l <= mid && r > mid)  87     {    88         oper2(2*p,l,mid,x);   89         oper2(2*p+1,mid+1,r,x);  90     }  91     else oper2(2*p+1,l,r,x);  92     if(tree[p].l != tree[p].r)    //記得更新父節點的最大最小值   93     {  94         tree[p].Max = max(tree[2*p].Max,tree[2*p+1].Max);  95         tree[p].Min = min(tree[2*p].Min,tree[2*p+1].Min);  96     }  97 }  98 int query(int p,int l)  99 { 100     int mid = (tree[p].l + tree[p].r) / 2; 101     if(tree[p].Max == tree[p].Min) 102     return tree[p].Max; 103     if(l <= mid) return query(2*p,l); 104     else return query(2*p+1,l); 105 } 106      107 int main() 108 { 109     int T,n; 110     scanf("%d",&T); 111     while(T--) 112     { 113         scanf("%d",&n); 114         tree[1].Max = -1; 115         tree[1].Min = 0x7fffffff; 116         tree[1].l = 1; 117         tree[1].r = n; 118         build(1); 119         int d; 120         for(int i = 1;i <= n;++i) 121         { 122             scanf("%d",&d); 123             push(1,i,d); 124         } 125         int q,t,l,r,x; 126         scanf("%d",&q); 127         while(q--) 128         { 129             scanf("%d%d%d%d",&t,&l,&r,&x); 130             if(t == 1) oper1(1,l,r,x); 131             else oper2(1,l,r,x); 132         } 133         for(int i = 1;i <= n;++i)    //輸出有點不同,PE了好幾次,最後也是有空格的  134         printf("%d ",query(1,i)); 135         puts(""); 136     } 137     return 0; 138 }

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved