• CTSC2016时空旅行


    当时看这道题AC的人数比较多,就开了这道题。

    很容易发现是这是一个有关凸包的题。

    然后不知道怎么维护凸包,一直在想cdq,感觉复杂度不行,于是被这玩意难住了……

    幸好有亲学长yyh造福人类的题解:https://blog.csdn.net/qwsin/article/details/70884985,十分详细,而且相对容易看懂些,脑回路跟我差不多

    发现主要是我没学线段树标记永久化,所以去学了一下这个东西:https://www.cnblogs.com/Hallmeow/p/8004676.html

    大概就是,为了懒得pushdown,就做一个标记,每次询问的时候,拿到这个标记,就直接更新答案……

    应用到这道题上,我们发现所有询问都是单点询问,就是说会每次都会走到线段树的最底层。

    这样就有个好处:我们往线段树的一段区间的凸包加一个点时,只有走到线段树上被区间完全包含的点的时候,在这里的凸包上加点,然后return

    中途没被修改区间完全覆盖的线段树上的地方,就不用在凸包上加点。

    然后这道题的主要特点是,用了很多排序,让凸包的优秀性质,最大得发挥。

    具体参考学长yyh的题解

    bz上又卡常,我是真的卡不过去,yyh的代码也要T……

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<vector>
    using namespace std;
    #define ll long long
    #define db double
    #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 maxn=5e5+7;
    const ll INF=1e18+7;
    ll n,m,c0,ans[maxn];//don't forget the earth
     
    char cc; ll ff;
    template<typename T>void read(T& aa) {
        aa=0;cc=getchar();ff=1;
        while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
        if(cc=='-') ff=-1,cc=getchar();
        while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
        aa*=ff;
    }
     
    int fir[maxn],nxt[maxn],to[maxn],e=0;
    void add(int x,int y) {
    //  printf("add:%d->%d
    ",x,y);
        to[++e]=y;nxt[e]=fir[x];fir[x]=e;
    }
     
    int dfn[maxn],end[maxn],dfn_clock=-1;
    void dfs(int pos) {
        dfn[pos]=++dfn_clock;
        for(int y=fir[pos];y;y=nxt[y]) dfs(to[y]);
        end[pos]=dfn_clock;
    }
     
    struct Plt{
        ll id,x,y,pos;
        Plt(){}
        Plt(ll id,ll x,ll y,ll pos):id(id),x(x),y(y),pos(pos){}
        bool operator < (const Plt& b) const{return x==b.x? y>b.y:x<b.x;}
    }plt[maxn];
    vector<int>del[maxn];
    bool cmp(const int a,const int b) {return dfn[a]<dfn[b];}
    int totp;
     
    struct Ask{
        ll qid,pos,k,x;
        Ask(){}
        Ask(ll qid,ll pos,ll k,ll x):qid(qid),pos(pos),k(k),x(x){}
        bool operator < (const Ask& b) const{return k>b.k;}
    }ask[maxn];
     
    struct Node{
        ll x,y;
        Node(){}
        Node(ll x,ll y):x(x),y(y){}
    }o,D;
     
    struct Seg{
        int p;//current pos on convex hull
        vector<Node> G;
        Seg(){G.clear();p=0;}
        void push(Node x) {G.push_back(x);}
        void pop() {G.pop_back();}
    }seg[4*maxn];
    ll ql,qr,qa,qb;
     
    ll get_ans(ll k,ll b,Node s) {return k*s.x+s.y+b;}
     
    void get_push(int pos) {
        ll X1,Y1,X2,Y2,r=seg[pos].G.size();
        while(r&&seg[pos].G[r-1].x==o.x) seg[pos].pop(),r--;
        while(r>=2) {
            X1=seg[pos].G[r-1].x-seg[pos].G[r-2].x;
            Y1=seg[pos].G[r-1].y-seg[pos].G[r-2].y;
            X2=o.x-seg[pos].G[r-2].x;
            Y2=o.y-seg[pos].G[r-2].y;
            if((db)Y1/X1<(db)Y2/X2) break;
            seg[pos].pop(); r--; 
        }
        seg[pos].push(o);
    }
     
    void chge(int pos,int l,int r) {
        if(l>=ql&&r<=qr) {
            get_push(pos);
            return;
        }
        int mid=(l+r)>>1;
        if(ql<=mid) chge(pos<<1,l,mid);
        if(qr>mid) chge(pos<<1|1,mid+1,r);
    }
     
    void get_insert(int i) {
        int x=plt[i].id,ld=dfn[plt[i].pos],rd=end[plt[i].pos];
        o=Node(plt[i].x,plt[i].y);
        sort(del[x].begin(),del[x].end(),cmp);
        int N=del[x].size()-1;
        For(i,0,N) {
            if(ld<dfn[del[x][i]]) {
                ql=ld; qr=min(rd,dfn[del[x][i]]-1);
                chge(1,1,n);
            }
            ld=max(ld,end[del[x][i]]+1);
            if(ld>rd) break;
        }
        if(ld<=rd) {ql=ld; qr=rd; chge(1,1,n);}
    }
     
    #define np seg[pos].p
     
    ll ud_ans(int pos) {
        if(!seg[pos].G.size()) return INF;
        ll rs=get_ans(qa,qb,seg[pos].G[np]),now,N=seg[pos].G.size();
        while(np+1<N) {
            now=get_ans(qa,qb,seg[pos].G[np+1]);
            if(now>=rs) break;
            rs=now; np++;
        }
        return rs;
    }
     
    ll q(int pos,int l,int r) {
        ll rs=ud_ans(pos);
        if(l==r) return rs;
        int mid=(l+r)>>1;
        if(ql<=mid) rs=min(rs,q(pos<<1,l,mid));
        if(qr>mid) rs=min(rs,q(pos<<1|1,mid+1,r));
        return rs;
    }
     
    int main() {
        read(n); read(m); read(c0);
        D=Node(0,c0);
        ll op,id,x,y,z,c,f;
        For(i,1,n-1) {
            read(op); read(f); read(id); add(f,i);
            if(!op) {
                read(x); read(y); read(z); read(c);
                plt[++totp]=Plt(id,x,x*x+c,i);
            }
            else del[id].push_back(i);
        }
        dfs(0);
        sort(plt+1,plt+totp+1);
        For(i,1,totp) get_insert(i);
        For(i,1,m) {
            read(id); read(x);
            ask[i]=Ask(i,dfn[id],-2*x,x*x);
            ans[i]=get_ans(-2*x,x*x,D);
        }
        sort(ask+1,ask+m+1);
        For(i,1,m) {
            ql=qr=ask[i].pos; qa=ask[i].k; qb=ask[i].x;
            if(ql) ans[ask[i].qid]=min(ans[ask[i].qid],q(1,1,n));
        }
        For(i,1,m) printf("%lld
    ",ans[i]);
        return 0;
    }
    
  • 相关阅读:
    《人月神话》阅读笔记2
    【个人作业】单词链
    【个人作业】找水王
    【团队】 冲刺一(10/10)
    【团队】 冲刺一(9/10)
    【个人作业】单词统计续
    【团队】 冲刺一(8/10)
    【团队】 冲刺一(7/10)
    【团队】 冲刺一(6/10)
    【团队】 冲刺一(5/10)
  • 原文地址:https://www.cnblogs.com/Serene-shixinyi/p/8989154.html
Copyright © 2020-2023  润新知