zoukankan      html  css  js  c++  java
  • 「BZOJ2391」Cirno的忧郁

    传送门

    设p[0] = (-10001,-10001)

    把所有点按p[0]极角排序,

    s[i][j]表示三角形p[0]p[i]p[j]内的总价值,若i到j极角增大则s为正,否则s为负。

    那么答案就是按顺序多边形每条边两个端点的s值之和的绝对值。

    如何求s

    枚举每个点x,建一颗平衡树,把极角排序在它后面的点一个个加入平衡树,树中的权值为按x极角排序的值。那么加入一个点y时,权值小于y的权值的所有点的和即为s[x][y]。

    //Achen
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<vector>
    #include<cstdio>
    #include<queue>
    #include<cmath>
    #define eps 1e-15
    #define For(i,a,b) for(int i=(a);i<=(b);i++)
    #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
    const int N=2007;
    typedef long long LL;
    typedef double db;
    using namespace std;
    int n,m,q,qs[N],rak[N];
    
    template<typename T>void read(T &x)  {
        char ch=getchar(); x=0; T f=1;
        while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
        if(ch=='-') f=-1,ch=getchar();
        for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    }
    
    struct pt {
        LL x,y,w; int id; db slop;
        pt(){}
        pt(LL x,LL y):x(x),y(y){}
    }p[N];
    pt operator - (const pt&A,const pt&B) { return pt(A.x-B.x,A.y-B.y); }
    LL cross(pt A,pt B) { return A.x*B.y-A.y*B.x; }
    LL dot(pt A,pt B) { return A.x*B.x+A.y*B.y; }
    LL length(pt A) { return dot(A,A); }
    int dcmp(db x) { return fabs(x)<=eps?0:(x>0?1:-1); } 
    bool operator <(const pt&A,const pt&B) { 
        return dcmp(A.slop-B.slop)>0||(dcmp(A.slop-B.slop)==0&&length(A-p[0])<length(B-p[0])); 
    } 
    
    db v[N];
    LL w[N],s[N][N],sum[N],rs;
    int rt,tot,l[N],r[N],hr[N];
    #define lc l[x]
    #define rc r[x]
    void update(int x) { sum[x]=sum[lc]+sum[rc]+w[x]; }
    
    void left(int &x) {
        int y=r[x];
        r[x]=l[y];
        l[y]=x;
        update(x);
        x=y;
        update(x);
    }
    
    void right(int &x) {
        int y=l[x];
        l[x]=r[y];
        r[y]=x;
        update(x);
        x=y;
        update(x);
    } 
    
    void insert(int &x,db y,LL ww) {
        if(!x) {
            x=++tot;
            hr[x]=rand();
            lc=rc=0;
            v[x]=y;
            sum[x]=w[x]=ww; 
            rs+=ww;
            return ;
        }
        if(v[x]<y) {
            rs+=sum[lc]+w[x];
            insert(rc,y,ww);
            if(hr[rc]<hr[x]) left(x);
        }
        else {
            insert(lc,y,ww);
            if(hr[lc]<hr[x]) right(x);
        }
        update(x);
    }
    
    LL solve(int k) {
        LL res=0;
        qs[k+1]=qs[1];
        For(i,1,k) 
            res+=s[rak[qs[i]]][rak[qs[i+1]]];
        return abs(res);
    }
    
    #define DEBUG
    int main() {
    #ifdef DEBUG
        freopen("2391.in","r",stdin);
        freopen("2391.out","w",stdout);
    #endif
        srand(998244353);
        read(n); read(m);
        For(i,1,n) read(p[i].x),read(p[i].y),p[i].id=i,p[i].w=0;
        For(i,1,m) read(p[n+i].x),read(p[n+i].y),read(p[n+i].w);
        p[0]=pt(-12345,-15432); 
        For(i,1,n+m) p[i].slop=atan2(p[i].y-p[0].y,p[i].x-p[0].x);
        sort(p+1,p+n+m+1);
        For(i,1,n+m) if(p[i].id) rak[p[i].id]=i;
        For(i,1,n+m) {
            rt=0; tot=0;
            For(j,i,n+m) {
                if(j==1008) {
                    int debug=1;
                }
                rs=0;
                insert(rt,atan2(p[j].y-p[i].y,p[j].x-p[i].x),p[j].w);
                s[i][j]=rs; s[j][i]=-rs;
            }
        }
        read(q);
        while(q--) {
            int k;
            read(k);
            For(i,1,k) read(qs[i]);
            printf("%lld
    ",solve(k)); 
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Java基础知识三点
    《计算机网络》读书笔记
    Shell编程初步
    《现代操作系统》读书笔记
    《数据库系统概论》读书笔记
    《数据结构》读书笔记
    Linux使用笔记
    【Thinking in Java】读书笔记
    算法题摘录六
    算法题摘录五
  • 原文地址:https://www.cnblogs.com/Achenchen/p/8662757.html
Copyright © 2011-2022 走看看