Luck and Love(二维线段树单点更新+区间查询+模板)

来源:互联网 发布:网络最火说唱歌手排名 编辑:程序博客网 时间:2024/05/19 04:56

Luck and Love

Time Limit : 10000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other)
Total Submission(s) : 32   Accepted Submission(s) : 13
Problem Description
世界上上最远的距离不是相隔天涯海角
而是我在你面前
可你却不知道我爱你
                ―― 张小娴

前段日子,枫冰叶子给Wiskey做了个征婚启事,聘礼达到500万哦,天哪,可是天文数字了啊,不知多少MM蜂拥而至,顿时万人空巷,连扫地的大妈都来凑热闹来了。―_―|||
由于人数太多,Wiskey实在忙不过来,就把统计的事情全交给了枫冰叶子,自己跑回家休息去了。这可够枫冰叶子忙的了,他要处理的有两类事情,一是得接受MM的报名,二是要帮Wiskey查找符合要求的MM中缘分最高值。
 

Input
本题有多个测试数据,第一个数字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) 所有输入的浮点数,均只有一位小数。
 

Output
对于每一次询问操作,在一行里面输出缘分最高值,保留一位小数。 对查找不到的询问,输出-1。
 

Sample Input
8I 160 50.5 60.0I 165 30.0 80.5I 166 10.0 50.0I 170 80.5 77.5Q 150 166 10.0 60.0Q 166 177 10.0 50.0I 166 40.0 99.9Q 166 177 10.0 50.00
 

Sample Output
80.550.099.9
 

Author
威士忌
 

Source
HDOJ 2007 Summer Exercise(3)- Hold by Wiskey
 

Statistic | Submit | Back

借鉴的其他人的代码,自己对线段树这个专题不是那么得心应手。

建一棵二维线段树,第一维是身高,由于没有低于100的,我们就可以把值减去99以缩减数组大小和更新查询的时间,然后由于第二维是活泼度是浮点型,我们就把值整体乘上10做成线段树,然后剩下的套模板就是了。。

代码:

#include <iostream>#include <stdio.h>#include <cstring>#include<math.h>#include<string>#include<stack>#include<queue>#include<list>#include<vector>#include <algorithm>using namespace std;#define INF 10086111#define lson k*2#define rson k*2+1#define M (l+r)/2int maxn[105*4][1005*4];int que;//询问结果int L1,L2,R1,R2;//因为数字比较多,开成全局就不用传来传去了,分别表示查询的身高区间和查询的活泼度区间void update1(int fk,int l,int r,int pos,int k,int v)//更新第二维,也就是活泼度,fk为第一维的节点下标{    if(l==r)//如果搜到了要更新的位置,更新    {        maxn[fk][k]=max(maxn[fk][k],v);        return;    }    int mid=M;    if(pos<=mid)        update1(fk,l,mid,pos,lson,v);    else        update1(fk,mid+1,r,pos,rson,v);    maxn[fk][k]=max(maxn[fk][lson],maxn[fk][rson]);//更新父区间}void update2(int k,int l,int r,int pos1,int pos2,int v)//更新第一维,pos1为要插入的身高,pos2为活泼度,v为缘分值{    update1(k,1,1000,pos2,1,v);//每到一次都要更新第二维    if(l==r)        return;    int mid=M;    if(pos1<=M)        update2(lson,l,mid,pos1,pos2,v);    else        update2(rson,mid+1,r,pos1,pos2,v);}void query1(int l,int r,int k,int fk)//询问第二维,也就是活泼度{    if(L2<=l&&r<=R2)//如果查到了要查询的子区间    {        que=max(que,maxn[fk][k]);//更新que        return;    }    int mid=M;    if(R2<=mid)        query1(l,mid,lson,fk);    else if(L2>mid)        query1(mid+1,r,rson,fk);    else    {        query1(l,mid,lson,fk);        query1(mid+1,r,rson,fk);    }}void query2(int l,int r,int k)//查询第一维,身高{    if(L1<=l&&r<=R1)//查好了第一维    {        query1(1,1000,1,k);//查第二维        return;    }    int mid=M;    if(R1<=mid)        query2(l,mid,lson);    else if(L1>mid)        query2(mid+1,r,rson);    else    {        query2(l,mid,lson);        query2(mid+1,r,rson);    }}int main(){    int i,j,k,n;    int a,b,v,h,h1,h2;    double e,o,e1,e2;    char s[10];    while(scanf("%d",&n)!=EOF&&n)    {        memset(maxn,-1,sizeof(maxn));//初始化-1        while(n--)        {            scanf("%s",s);            if(s[0]=='I')            {                scanf("%d%lf%lf",&h,&e,&o);                a=h-99;//减去以节省时间空间                b=e*10;//乘上10做成线段树                v=o*10;                update2(1,1,100,a,b,v);            }            else            {                scanf("%d%d%lf%lf",&h1,&h2,&e1,&e2);                if(h1>h2)//防止有坑                    swap(h1,h2);                if(e1>e2)                    swap(e1,e2);                L1=h1-99;                R1=h2-99;                L2=e1*10;                R2=e2*10;                que=-1;                query2(1,100,1);                if(que==-1)                    printf("-1\n");                else                    printf("%d.%d\n",que/10,que%10);            }        }    }    return 0;}


阅读全文
0 0
原创粉丝点击