HDU 1823 Luck and Love 二維線段樹 / 矩形樹

來源:互聯網
上載者:User

題意:
本題有多個測試資料,第一個數字M,表示接下來有連續的M個操作,當M=0時處理中止。接下來是一個操作符C。當操作符為‘I’時,表示有一個MM報名,後面接著一個整數,H表示身高,兩個浮點數,A表示活潑度,L表示緣分值。 (100<=H<=200, 0.0<=A,L<=100.0)當操作符為‘Q’時,後面接著四個浮點數,H1,H2表示身高區間,A1,A2表示活潑度區間,輸出符合身高和活潑度要求的MM中的緣分最高值。 (100<=H1,H2<=200, 0.0<=A1,A2<=100.0)所有輸入的浮點數,均只有一位小數。

題解:
注意浮點數的處理,一般來說可以離散化,或者化作整數處理。
二維線段樹,第一維度每一個節點都包含第二維度一顆線段樹。這種方式對於更高的維度就不是適用了。這時可用矩形樹。

#include <iostream>using namespace std;#define N 270#define M 2100int lch ( int x ) { return x * 2; }int rch ( int x ) { return x * 2 + 1; }int max ( int x, int y ) { return x > y ? x : y; }struct sonNode{    int l, r, val;    void getlr ( int tl, int tr )    {        l = tl; r = tr;    }};struct parentNode{    int l, r;    sonNode son[M];    void getlr ( int tl, int tr )     {        l = tl; r = tr;    }    };parentNode node[N];void sub_build ( int f, int u, int l, int r ){    node[f].son[u].getlr ( l, r );    node[f].son[u].val = -1;    if ( l == r ) return;    int mid = ( l + r ) / 2;    sub_build ( f, lch(u), l, mid );    sub_build ( f, rch(u), mid+1, r );}void build ( int f, int l1, int r1, int l2, int r2 ){    node[f].getlr ( l1, r1 );    sub_build ( f, 1, l2, r2 );    if ( l1 == r1 ) return;    int mid = ( l1 + r1 ) / 2;    build ( lch(f), l1, mid, l2, r2 );    build ( rch(f), mid+1, r1, l2, r2 );}void sub_update ( int f, int u, int pos2, int val ){if ( u > M ) return;   /* 此條件不可忽略 */    node[f].son[u].val = max ( node[f].son[u].val, val );if ( node[f].son[u].l == pos2 && node[f].son[u].r == pos2 ){node[f].son[u].val = max ( node[f].son[u].val, val );return;}    int mid = ( node[f].son[u].l + node[f].son[u].r ) / 2;    if ( pos2 <= mid )        sub_update ( f, lch(u), pos2, val );    else        sub_update ( f, rch(u), pos2, val );}void update ( int f, int pos1, int pos2, int val ){if ( f > N ) return;    sub_update ( f, 1, pos2, val );if ( node[f].l == node[f].r ) return;    int mid = ( node[f].l + node[f].r ) / 2;    if ( pos1 <= mid )        update ( lch(f), pos1, pos2, val );    else        update ( rch(f), pos1, pos2, val );}int sub_query ( int f, int u, int l2, int r2 ){    if ( u > M ) return -1;  // !!!    if ( node[f].son[u].l == l2 && node[f].son[u].r == r2 )        return node[f].son[u].val;    int mid = ( node[f].son[u].l + node[f].son[u].r ) / 2;    if ( r2 <= mid )        return sub_query ( f, lch(u), l2, r2 );    else if ( l2 > mid )        return sub_query ( f, rch(u), l2, r2 );    else        return max ( sub_query(f,lch(u),l2,mid), sub_query(f,rch(u),mid+1,r2) );}int query ( int f, int l1, int r1, int l2, int r2 ){if ( f > N ) return -1;   //!!!    if ( node[f].l == l1 && node[f].r == r1 )        return sub_query ( f, 1, l2, r2 );    int mid = ( node[f].l + node[f].r ) / 2;    if ( r1 <= mid )        return query ( lch(f), l1, r1, l2, r2 );    else if ( l1 > mid )        return query ( rch(f), l1, r1, l2, r2 );    else        return max ( query(lch(f),l1,mid,l2,r2), query(rch(f),mid+1,r1,l2,r2) );}int main (){    char ch[3];    int m, h, hl, hr, ans;    double a, l, al, ar;    //freopen("a.txt","r",stdin);    while ( scanf("%d",&m) != EOF && m )    {        memset(node,0,sizeof(node));        build ( 1, 100, 200, 0, 1000 );        while ( m-- )        {                scanf("%s",ch);            if ( ch[0] == 'I' )            {                scanf("%d%lf%lf", &h, &a, &l );                update ( 1, h, (int)(a*10), (int)(l*10) );            }            else            {                scanf("%d%d%lf%lf", &hl, &hr, &al, &ar);                if ( hl > hr ) swap ( hl, hr );                if ( al > ar ) swap ( al, ar );                ans = query ( 1, hl, hr, (int)(al*10), (int)(ar*10) );                if ( ans < 0 ) printf("-1\n");                else printf("%.1lf\n", ans/10.0 );            }        }    }    return 0;}

下面是我用矩形樹寫的,老是超記憶體,自己不太會最佳化,沒辦法了。算學習下演算法,就不糾結它了。

#include <algorithm>#include <cmath>#include <iostream>using namespace  std;#define N 200000#define eps 0.00001double bset[N];int n, size, cnt, tol;struct tree{int son[4];int x1, y1, x2, y2;double love;} node[N*4];struct operation{int kind;double h1, h2, a1, a2, love;} oper[N];double max ( double a, double b ){return a > b ? a : b;}int bfind ( double key ){int l = 1, r = cnt;while ( l <= r ){int mid = ( l + r ) / 2;if ( fabs(bset[mid]-key) < eps )return mid;if ( bset[mid] > key )r = mid - 1;elsel = mid + 1;}return -1;}bool cross( int u, int x1, int y1, int x2, int y2 ) //判斷兩矩形是否相交{    int x3 = node[u].x1;    int y3 = node[u].y1;    int x4 = node[u].x2;    int y4 = node[u].y2;     if ( y2 < y3 || y4 < y1 || x4 < x1 || x2 < x3)        return false;    return true;}void build ( int x1, int y1, int x2, int y2 ) {int u = ++tol; /* tol 表示節點編號 */node[u].love = -1.0;node[u].x1 = x1; node[u].y1 = y1;node[u].x2 = x2; node[u].y2 = y2;if ( x1 == x2 && y1 == y2 )return;int midx = ( x1 + x2 ) / 2;int midy = ( y1 + y2 ) / 2;if ( x1 <= midx && y1 <= midy )   /* 左下方子矩形 */{node[u].son[0] = tol + 1;build ( x1, y1, midx, midy ); }else node[u].son[0] = 0;if ( midx + 1 <= x2 && midy + 1 <= y2 ) /* 右上方子矩形 */{node[u].son[1] = tol + 1;build ( midx+1, midy+1, x2, y2 ); }else node[u].son[1] = 0;if ( x1 <= midx && midy + 1 <= y2 ) /*左上方*/{node[u].son[2] = tol + 1;build ( x1, midy + 1, midx, y2 ); }else node[u].son[2] = 0;if ( midx + 1 <= x2 && y1 <= midy ) /* 右下方 */{node[u].son[3] = tol + 1;build ( midx + 1, y1, x2, midy ); }else node[u].son[3] = 0;}void update ( int u, int x, int y, double val ){if ( node[u].x1 == node[u].x2 && node[u].y1 == node[u].y2 ){node[u].love = max ( node[u].love, val );return;}int midx = ( node[u].x1 + node[u].x2 ) / 2;int midy = ( node[u].y1 + node[u].y2 ) / 2;if ( x <= midx ){if ( y <= midy )update ( node[u].son[0], x, y, val );elseupdate ( node[u].son[2], x, y, val );}else{if ( y <= midy )update ( node[u].son[3], x, y, val );elseupdate ( node[u].son[1], x, y, val );}double temp = -1;for ( int i = 0; i < 4; ++i )temp = max ( temp, node[node[u].son[i]].love );node[u].love = temp;}double query ( int u, int x1, int y1, int x2, int y2 ){if ( ! cross(u,x1,y1,x2,y2)  || node[u].love < 0 )return -1.0;if ( x1 <= node[u].x1 && y1 <= node[u].y1 && node[u].x2 <= x2 && node[u].y2 <= y2 )return node[u].love;double temp = -1.0;for ( int i = 0; i < 4; ++i )temp = max ( temp, query ( node[u].son[i], x1, y1, x2, y2) );return temp;}int main (){char ch[3];int i;//freopen("a.txt","r",stdin);while ( scanf("%d",&n) != EOF && n ){size = 0;memset(bset,0,sizeof(bset));memset(node,0,sizeof(node));memset(oper,0,sizeof(oper));for ( i = 1; i <= n; ++i ){scanf("%s",ch);if ( ch[0] == 'I' ){oper[i].kind = 0;scanf("%lf%lf%lf", &oper[i].h1, &oper[i].a1, &oper[i].love );bset[++size] = oper[i].h1;bset[++size] = oper[i].a1;}else{oper[i].kind = 1;scanf("%lf%lf%lf%lf", &oper[i].h1, &oper[i].h2, &oper[i].a1, &oper[i].a2 );bset[++size] = oper[i].h1;bset[++size] = oper[i].h2;bset[++size] = oper[i].a1;bset[++size] = oper[i].a2;}}sort ( bset+1, bset+size+1 );for ( cnt = i = 1; i <= size; ++i ) /* 離散化 */{if ( bset[cnt] != bset[i] )bset[++cnt] = bset[i];}tol = 0;build ( 1, 1, cnt, cnt ); for ( i = 1; i <= n; ++i ){if ( oper[i].kind == 0 ){int x = bfind ( oper[i].h1 );int y = bfind ( oper[i].a1 );update ( 1, x, y, oper[i].love );}else{int x1 = bfind ( oper[i].h1 );int x2 = bfind ( oper[i].h2 );int y1 = bfind ( oper[i].a1 );int y2 = bfind ( oper[i].a2 );if ( x1 > x2 ) swap(x1,x2);if ( y1 > y2 ) swap(y1,y2);double ans =  query ( 1, x1, y1, x2, y2 );if ( ans < 0 )printf("-1\n");else    printf ("%.1lf\n", ans );}}}return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.