zoukankan      html  css  js  c++  java
  • [Codeforces]853E

    题目大意:给出平面上$n$个带权点$f_{i}$,再给出$k$个向量$v_{i}$,每次询问给出一个点$p$和一个值$t$,求能满足$f_{i}+sum w_{j}v_{j}=p(-t<=w_{j}<=t)$的$f_{i}$的点权和。($n,q<=10^5,k<=10$)

    做法:由于$v_{i}$与$-v_{i}$等价,我们先把每个向量的横坐标变成非负(在此基础上尽量使纵坐标也非负),再把询问的式子化成$p-tsum v_{j}+sum w_{j}v_{j}(0<=w_{j}<=2t)$,令$P=p-tsum v_{j}$,则合法的$f_{i}$会在这样一个凸多边形内:从$P$点开始,按斜率从小到大的顺序依次把向量接起来得到一个下凸壳,再从$P$点开始,按斜率从大到小顺序再接出一个上凸壳。现在我们要计算这个凸多边形内的点权和,我们只要知道每条边下方(以两个端点向下竖直画射线与这条边围成的区域)的点权和,上凸壳减下凸壳就是答案。由于斜率只有$k$种,我们每种斜率都做一遍,算出所有同斜率的边以及所有点在这个斜率下的截距,按这个截距的大小顺序,按横坐标建线段树即可统计。时间复杂度$O(k(n+q)logn)$。

    一些实现细节可以参见如下代码:

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    #define ll long long
    inline int read()
    {
        int x,f=1;char c;
        while((c=getchar())<'0'||c>'9')if(c=='-')f=0;
        for(x=c-'0';(c=getchar())>='0'&&c<='9';)x=x*10+c-'0';
        return f?x:-x;
    }
    #define MK 10
    #define MN 100000
    #define ps(x) (upper_bound(c+1,c+cn+1,x)-c-1)
    struct vec{int x,y;}v[MK+5];
    struct work{double a;int x,y,z;}w[MN*2+5];
    bool cmpv(const vec&a,const vec&b){return atan2(a.y,a.x)<atan2(b.y,b.x);}
    bool cmpw(const work&a,const work&b){return fabs(a.a-b.a)<1e-7?a.z<b.z:a.a<b.a;}
    int x[MN+5],y[MN+5],a[MN+5],c[MN+5],cn,sx,sy,px[MN+5],py[MN+5],t[MN+5];
    ll ans[MN+5],s[MN+5];
    void add(int k,int x){for(;k<=MN;k+=k&-k)s[k]+=x;}
    ll sum(int k){ll res=0;for(;k;k-=k&-k)res+=s[k];return res;}
    int main()
    {
        int k,n,q,i,j;
        k=read();n=read();q=read();
        for(i=1;i<=k;++i)
        {
            v[i].x=read();v[i].y=read();
            if(v[i].x<0)v[i].x=-v[i].x,v[i].y=-v[i].y;
            if(!v[i].x&&v[i].y<0)v[i].y=-v[i].y;
            sx+=v[i].x;sy+=v[i].y;
        }
        sort(v+1,v+k+1,cmpv);
        for(i=1;i<=n;++i)c[i]=x[i]=read(),y[i]=read(),a[i]=read();
        sort(c+1,c+n+1);cn=unique(c+1,c+n+1)-c-1;
        for(i=1;i<=q;++i)px[i]=read(),py[i]=read(),t[i]=read(),px[i]-=sx*t[i],py[i]-=sy*t[i],t[i]<<=1;
        for(i=1;i<=k;++i)
        {
            if(!v[i].x){for(j=1;j<=q;++j)py[j]+=v[i].y*t[j];continue;}
            for(j=1;j<=n;++j)w[j]=(work){y[j]-(double)x[j]*v[i].y/v[i].x,x[j],a[j],0};
            for(j=1;j<=q;++j)w[n+j]=(work){py[j]-(double)px[j]*v[i].y/v[i].x,px[j],px[j]+v[i].x*t[j],-j},
                px[j]+=v[i].x*t[j],py[j]+=v[i].y*t[j];
            sort(w+1,w+n+q+1,cmpw);
            memset(s,0,sizeof(s));
            for(j=1;j<=n+q;++j)
                if(w[j].z)ans[-w[j].z]-=sum(ps(w[j].y))-sum(ps(w[j].x-(i<2)));
                else add(ps(w[j].x),w[j].y);
        }
        for(i=1;i<=k;++i)
        {
            if(!v[i].x)break;
            for(j=1;j<=n;++j)w[j]=(work){y[j]-(double)x[j]*v[i].y/v[i].x,x[j],a[j],0};
            for(j=1;j<=q;++j)w[n+j]=(work){py[j]-(double)px[j]*v[i].y/v[i].x,px[j]-v[i].x*t[j],px[j],j},
                px[j]-=v[i].x*t[j],py[j]-=v[i].y*t[j];
            sort(w+1,w+n+q+1,cmpw);
            memset(s,0,sizeof(s));
            for(j=1;j<=n+q;++j)
                if(w[j].z)ans[w[j].z]+=sum(ps(w[j].y-(i>1)))-sum(ps(w[j].x-1));
                else add(ps(w[j].x),w[j].y);
        }
        for(i=1;i<=q;++i)printf("%I64d
    ",ans[i]);
    }
  • 相关阅读:
    Head first javascript(七)
    Python Fundamental for Django
    Head first javascript(六)
    Head first javascript(五)
    Head first javascript(四)
    Head first javascript(三)
    Head first javascript(二)
    Head first javascript(一)
    Sicily 1090. Highways 解题报告
    Python GUI programming(tkinter)
  • 原文地址:https://www.cnblogs.com/ditoly/p/CF853E.html
Copyright © 2011-2022 走看看