三分

来源:互联网 发布:mmd动作数据大全下载 编辑:程序博客网 时间:2024/05/17 08:10

题:

bzoj3330
bzoj3203YES
bzoj3533YES
bzoj3874
bzoj1857YES
bzoj1229YES

bzoj3533☆

题意:

维护一个向量集合,在线支持以下操作:
"Axy(|x||y|108)":加入向量(x,y);
"Qxylr(|x||y|1081LRT,其中T为已经加入的向量个数)询问第L个到第R个加入的向量与向量(x,y)的点积的最大值。
集合初始时为空。

分析:

设询问点为(x,y),对应答案最大的点为(x0,y0)
首先(x0,y0)一定在区间[l,r]区间中所有点的凸包上。且
y0(x0,y0)在上凸壳上
y<0(x0,y0)在下凸壳上
那么用线段树维护一下区间,但假如每次插入都更新凸包的话时间就爆炸了。发现如果区间右端点还没插入时这整段区间是不会查询的。于是乎只有插入区间右端点是才更新整个区间的上下凸壳。嗯~时间复杂度就是O(nlog2n)了。

#include<cstdio>#include<cstring>#include<algorithm>#include<string>using namespace std;typedef long long LL;const LL inf=21333333333333333;const int N=1048576;int n,m,x,y,l,r,v[N],size;long long lastans,ans;struct node{int x,y,l,r,op;}g[N];char s[N],tt[N];struct point{    LL x,y;    point(){}    point(int _x,int _y):x(_x),y(_y){}    friend point operator - (point a,point b){        return point(a.x-b.x,a.y-b.y);    }    friend point operator + (point a,point b){        return point(a.x+b.x,a.y+b.y);    }    friend LL operator * (point a,point b){        return a.x*b.y-a.y*b.x;    }    friend LL operator ^ (point a,point b){        return a.x*b.x+a.y*b.y;    }    friend bool operator < (point a,point b){        if (a.x==b.x)            return a.y<b.y;        return a.x<b.x;    }}p[N],t[N];struct range{    point *up,*dw;    int ut,dt;    void gao(int l,int r){        up=new point[r-l+2];        dw=new point[r-l+2];        int top=0;ut=dt=0;        for (int i=l;i<=r;i++)            t[++top]=p[i];        sort(t+1,t+top+1);        for (int i=1;i<=top;i++){            while (ut>1 && (t[i]-up[ut])*(up[ut]-up[ut-1])<=0) ut--;            up[++ut]=t[i];            while (dt>1 && (dw[dt]-dw[dt-1])*(t[i]-dw[dt])<=0) dt--;            dw[++dt]=t[i];        }    }    LL query(point k){        LL res=-inf;        if (k.y>=0){            int l=1,r=ut;            while (r-l>2){                int ll=l+(r-l)/3;                int rr=r-(r-l)/3;                if ((up[ll]^k)<(up[rr]^k))                    l=ll; else r=rr;            }            for (int i=l;i<=r;i++)                res=max(res,up[i]^k);        } else {            int l=1,r=dt;            while (r-l>2){                int ll=l+(r-l)/3;                int rr=r-(r-l)/3;                if ((dw[ll]^k)<(dw[rr]^k))                    l=ll; else r=rr;            }            for (int i=l;i<=r;i++)                res=max(res,dw[i]^k);        }        return res;    }}tree[N];LL query(int rt,int l,int r,int ll,int rr,point k){    if (ll<=l && r<=rr){        if (!v[rt]) tree[rt].gao(l,r);        v[rt]=1;return tree[rt].query(k);    }    int mid=(l+r)>>1;LL res=-inf;    if (ll<=mid) res=max(res,query(2*rt,l,mid,ll,rr,k));    if (rr> mid) res=max(res,query(2*rt+1,mid+1,r,ll,rr,k));    return res;}int read(){      int res=0,f=1;char c=getchar();      while(!isdigit(c))f=f==-1||c=='-'?-1:1,c=getchar();      while(isdigit(c))res=res*10+c-'0',c=getchar();      return (res*f);  } int gao(){return lastans&0x7fffffff;}int main(){    freopen("a.in","r",stdin);    scanf("%d%s",&m,s);    for (int i=1;i<=m;i++){        scanf("%s",tt);        if (tt[0]=='A'){            x=read();y=read();            g[i].x=x;g[i].y=y;            g[i].op=1;n++;        } else {            x=read();y=read();            l=read();r=read();            g[i].x=x;g[i].y=y;            g[i].l=l;g[i].r=r;            g[i].op=2;        }    }    for (int i=1;i<=m;i++){        if (g[i].op==1){            x=g[i].x;y=g[i].y;            if (s[0]!='E'){                x^=gao();y^=gao();            }            p[++size]=point(x,y);        } else {            x=g[i].x;y=g[i].y;            l=g[i].l;r=g[i].r;            if (s[0]!='E'){                x^=gao();y^=gao();                l^=gao();r^=gao();            }            lastans=query(1,1,n,l,r,point(x,y));            printf("%lld\n",lastans);        }    }}

bzoj1857

三分套三分~就是分别三分两线段。
证明:http://blog.csdn.net/geotcbrl/article/details/48833339

#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;double p,q,len,ans;const double eps=0.00000001;struct node{    double x,y;    node(){}    node(double _x,double _y):x(_x),y(_y){}    friend double dis(node a,node b){        return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));    }    friend node operator - (node a,node b){        return node(a.x-b.x,a.y-b.y);    }    friend node operator + (node a,node b){        return node(a.x+b.x,a.y+b.y);    }    friend node operator / (node a,double x){        return node(a.x/x,a.y/x);    }}a,b,c,d;double find(node a){    node l=c,r=d;    double res=min(dis(a,r)/len,(dis(a,l)+dis(l,r))/len);    while (dis(l,r)>eps){        node ll=l+(r-l)/3.0;        node rr=r-(r-l)/3.0;        double t1=dis(d,ll)/q,t2=dis(d,rr)/q;        t1+=dis(ll,a)/len,t2+=dis(rr,a)/len;        if (t1<t2)             res=min(res,t1),r=rr; else            res=min(res,t2),l=ll;    }    return res;}int main(){    freopen("a.in","r",stdin);    freopen("a.out","w",stdout);    scanf("%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y);    scanf("%lf%lf%lf%lf",&c.x,&c.y,&d.x,&d.y);    scanf("%lf%lf%lf",&p,&q,&len);    node l=a,r=b;ans=min(find(a),dis(l,r)/p+find(b));    while (dis(l,r)>eps){        node ll=l+(r-l)/3.0;        node rr=r-(r-l)/3.0;        double t1=dis(a,ll)/p,t2=dis(a,rr)/p;        double r1=find(ll),r2=find(rr);        r1+=t1;r2+=t2;        if (r1<r2)            ans=min(ans,r1),r=rr; else            ans=min(ans,r2),l=ll;    }    printf("%.2lf\n",ans);}

bzoj1229

若天数少的话就可以用费用流水掉了。
不然就贪心乱搞。
显然能去慢洗肯定比去快洗好(快洗比慢洗贵)。
现在问题来了,我们究竟要多少玩具捏。三分一波一开始的玩具个数(不会证明)然后在贪心乱搞一下就好了。

int gao(int x){    sl.clear();qk.clear();tm.clear();    int res=x*(tc-c2);    sl.push_back(node(0,x));    for (int i=1;i<=d;i++){        while (!tm.empty() && i-tm.front().x>=n1)            qk.push_back(tm.front()),tm.pop_front();        while (!qk.empty() && i-qk.front().x>=n2)            sl.push_back(qk.front()),qk.pop_front();        int T=t[i];        while (T){            if (!sl.empty()){                if (sl.back().c>=T){                    sl.back().c-=T;                    res+=T*c2;T=0;                } else {                    T-=sl.back().c;                    res+=sl.back().c*c2;                    sl.pop_back();                }            } else            if (!qk.empty()){                if (qk.back().c>=T){                    qk.back().c-=T;                    res+=T*c1;T=0;                } else {                    T-=qk.back().c;                    res+=qk.back().c*c1;                    qk.pop_back();                }            } else return inf;        }        tm.push_back(node(i,t[i]));    }    return res;}
0 0
原创粉丝点击