zoukankan      html  css  js  c++  java
  • dtoi3733 New Home

    题意:

         五福街是一条笔直的道路,这条道路可以看成一个数轴,街上每个建筑物的坐标都可以用一个整数来表示。小明是一位时光旅行者,他知道在这条街上,在过去现在和未来共有 n个商店出现。第 i个商店可以使用四个整数 xi,ti,ai,bi描述,它们分别表示:商店的坐标、商店的类型、商店开业的年份、商店关闭的年份。

    小明希望通过时光旅行,选择一个合适的时间,住在五福街上的某个地方。他给出了一份他可能选择的列表,上面包括了 q个询问,每个询问用二元组 (坐标,时间)表示。第 i对二元组用两个整数 li,yi描述,分别表示选择的地点 li和年份 yi

    现在,他想计算出在这些时间和地点居住的生活质量。他定义居住的不方便指数为:在居住的年份,离居住点最远的商店类型到居住点的距离。类型 t的商店到居住点的距离定义为:在指定的年份,类型 t的所有营业的商店中,到居住点距离最近的一家到居住点的距离。我们说编号为 i的商店在第 y年在营业当且仅当 aiybi 。注意,在某些年份中,可能在五福街上并非所有 k种类型的商店都有至少一家在营业。在这种情况下,不方便指数定义为 -1

    你的任务是帮助小明求出每对(坐标,时间)二元组居住的不方便指数。

    题解:

         先将询问按照时间排序,离线来做。

         这样我们按时间顺序插入/删除商店,对于一个询问,我们首先可以二分答案,接下来问题变成了求一段区间中有多少种不同的元素。那么这里有一个做法,就是将每一个点的权值设为nex[i],nex[i]表示下一个跟当前商店类型相同的商店的位置,然后插入线段树中,查询l,r中有多少nex[i]大于r。这可以树套树解决,但是分析复杂度,发现有3个log,显然是不可能过的。

         再分析一下问题的性质,我们发现并不需要求有多少种不同的元素,只需要求有没有所有的元素即可。我们可以转变思路,只需要判断[0,l-1]中所有nex[i]的最大值是否小于等于r即可。这里有个边界,我们假定所有类型的商店每时每刻在0和Max+1的位置都分别开设着。这样我们就可以在两个log的时间内解决这道题,使用线段树维护即可。

         但是本题有一个非常繁琐的东西,就是重复元素。我们需要用multiset在线段树的叶子中记录下元素用于删除插入,还要考虑新商店开设的位置重复的问题等等,所以也需要multiset维护。导致了常数的巨大无比,卡了好久才过。

    #include<cstdio>
    #include<set>
    #include<vector>
    #include<algorithm>
    #include<cstdlib>
    using namespace std;
    const int INF=1e8;
    int n,k,m,ans[300002],cnt=1;
    typedef struct{
        int Max,ls,rs;
        multiset<int>a;
    }P;
    typedef struct{
        int x,t,a,b;
    }PP;
    typedef struct{
        bool u;
        int x,t;
    }PPP;
    typedef struct{
        int x,tim,num;
    }PPPP;
    bool cmp(PPPP aa,PPPP bb){
        return (aa.tim<bb.tim);
    }
    P p[10000002];
    PP d[300002];
    multiset<int>q[300002];
    vector<PPP>g[300002];
    PPPP h[300002];
    int lb(int z,int lef,int righ){
        int mid;
        while(lef<righ)
        {
            mid=(lef+righ)/2;
            if (h[mid].tim>=z)righ=mid;else lef=mid+1;
        }
        return lef;
    }
    int ub(int z,int lef,int righ){
        int mid;
        while(lef<righ)
        {
            mid=(lef+righ)/2;
            if (h[mid].tim<=z)lef=mid+1;else righ=mid;
        }
        return lef;
    }
    void gengxin(int root,int begin,int end,int wz,int z,int th,bool u){
        if (begin==end)
        {
            if (!u)
            {
                multiset<int>::iterator it;it=p[root].a.find(z);
                p[root].a.erase(it);
                if (th!=-1)p[root].a.insert(th);
            }
            else p[root].a.insert(z);
            if (p[root].a.empty())p[root].Max=0;
            else
            {
                multiset<int>::iterator it=p[root].a.end();it--;
                p[root].Max=*it;
            }
            return;
        }
        int mid=(begin+end)/2;
        if (wz<=mid)
        {
            if (!p[root].ls)p[root].ls=++cnt;
            gengxin(p[root].ls,begin,mid,wz,z,th,u);
        }
        else
        {
            if (!p[root].rs)p[root].rs=++cnt;
            gengxin(p[root].rs,mid+1,end,wz,z,th,u);
        }
        p[root].Max=max(p[p[root].ls].Max,p[p[root].rs].Max);
    }
    int chaxun(int root,int begin,int end,int begin2,int end2){
        if (!root || begin>end2 || end<begin2)return 0;
        if (begin>=begin2 && end<=end2)return p[root].Max;
        int mid=(begin+end)/2;
        return max(chaxun(p[root].ls,begin,mid,begin2,end2),chaxun(p[root].rs,mid+1,end,begin2,end2));
    }
    int read(){
        int f=0;char ch=getchar();
        while(ch<'0' || ch>'9')ch=getchar();
        while(ch>='0' && ch<='9'){f=f*10+ch-48;ch=getchar();}
        return f;
    }
    int main()
    {
        n=read();k=read();m=read();
        for (int i=1;i<=n;i++)
        {
            d[i].x=read();d[i].t=read();d[i].a=read();d[i].b=read();
        }
        for (int i=1;i<=m;i++)
        {
            h[i].x=read();h[i].tim=read();h[i].num=i;
        }
        sort(h+1,h+m+1,cmp);
        for (int i=1;i<=n;i++)
        {
            int l=lb(d[i].a,1,m),r=ub(d[i].b,1,m+1);
            if (l==r)continue;
            PPP aa;aa.u=1;aa.x=d[i].x;aa.t=d[i].t;
            g[l].push_back(aa);
            aa.u=0;
            g[r].push_back(aa);
        }
        for (int i=1;i<=k;i++)
        {
            q[i].insert(0);q[i].insert(INF+1);
            gengxin(1,0,INF+1,0,INF+1,0,1);
        }
        for (int i=1;i<=m;i++)
        {
            for (int j=0;j<g[i].size();j++)
            {
                int tt=g[i][j].t,xx=g[i][j].x;
                if (g[i][j].u)
                {
                    multiset<int>::iterator ls,nx;
                    nx=ls=q[tt].lower_bound(xx);ls--;
                    if (*nx!=xx)
                    {
                        gengxin(1,0,INF+1,*ls,*nx,xx,0);
                        gengxin(1,0,INF+1,xx,*nx,0,1);
                    }
                    q[tt].insert(xx);
                }
                else
                {
                    multiset<int>::iterator ls,nx,it;
                    it=q[tt].find(xx);
                    nx=ls=q[tt].lower_bound(xx);nx++;
                    if (*nx!=xx)
                    {
                        ls--;
                        gengxin(1,0,INF+1,*ls,xx,*nx,0);
                        gengxin(1,0,INF+1,xx,*nx,-1,0);
                    }
                    q[tt].erase(it);
                }
            }
            int lef=0,righ=max(h[i].x-1,INF-h[i].x)+1,mid;
            while(lef<righ)
            {
                mid=(lef+righ)/2;
                int l=max(h[i].x-mid,1),r=min(h[i].x+mid,INF);
                if (chaxun(1,0,INF+1,0,l-1)<=r)righ=mid;else lef=mid+1;
            }
            if (lef!=max(h[i].x-1,INF-h[i].x)+1)ans[h[i].num]=lef;else ans[h[i].num]=-1;
        }
        for (int i=1;i<=m;i++)printf("%d
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    思维探索者:理解了才是真正的学习 理解会带来巨大的好处
    思维探索者:让记忆与学习更有效率 别在别人的思考中得意着
    思维探索者:从问题到答案的思维过程 像侦探一样思考
    android-HttpClient上传信息(包括图片)到服务端
    java web每天定时执行任务
    基础总结篇之一:Activity生命周期
    Spring面试题一
    J2EE用监听器实现同一用户只能有一个在线
    notepad++快捷键大全
    python for循环巧妙运用(迭代、列表生成式)
  • 原文地址:https://www.cnblogs.com/1124828077ccj/p/12250858.html
Copyright © 2011-2022 走看看