BZOJ3533 SDOI2014 向量集

55 篇文章 0 订阅
2 篇文章 0 订阅

SDOI2014 向量集

Time Limit: 25 Sec Memory Limit: 512 MB
维护一个向量集合,在线支持以下操作:
“A x y (|x|,|y| < =10^8)”:加入向量(x,y);
” Q x y l r (|x|,|y| < =10^8,1 < =L < =R < =T,其中T为已经加入的向量个数)询问第L个到第R个加入的向量与向量(x,y)的点积的最大值。
集合初始时为空。
Input
输入的第一行包含整数N和字符s,分别表示操作数和数据类别;
接下来N行,每行一个操作,格式如上所述。
请注意s≠’E’时,输入中的所有整数都经过了加密。你可以使用以下程序
得到原始输入:
inline int decode (int x long long lastans) {
return x ^ (lastans & Ox7fffffff);
}
function decode
begin
其中x为程序读入的数,lastans为之前最后一次询问的答案。在第一次询问之前,lastans=0。
注:向量(x,y)和(z,W)的点积定义为xz+yw。
Output
对每个Q操作,输出一个整数表示答案。
Sample Input
6 A
A 3 2
Q 1 5 1 1
A 15 14
A 12 9
Q 12 8 12 15
Q 21 18 19 18
Sample Output
13
17
17
解释:解密之后的输入为
6 E
A 3 2
Q 1 5 1 1
A 2 3
A 1 4
Q 1 5 1 2
Q 4 3 2 3
HINT
1 < =N < =4×10^5
新加数据一组..2015.315

//CSDN 世界大佬的题解 
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 400400
#define LL long long
struct Point{
    LL x,y;
    Point() {}
    Point(LL a,LL b):
        x(a),y(b) {}
    friend Point operator + (const Point &p1,const Point &p2){
        return Point(p1.x+p2.x,p1.y+p2.y);
    }
    friend Point operator - (const Point &p1,const Point &p2){
        return Point(p1.x-p2.x,p1.y-p2.y);
    }
    friend LL operator * (const Point &p1,const Point &p2){
        return p1.x*p2.y-p1.y*p2.x;
    }
    friend LL operator ^ (const Point &p1,const Point &p2){
        return p1.x*p2.x+p1.y*p2.y;
    }
    friend bool operator < (const Point &p1,const Point &p2){
        return p1.x<p2.x || p1.x==p2.x&&p1.y<p2.y;
    }
};
int n,tot;
char type[10];
LL Last_Ans;
void Cover_Merge(const vector<Point> &h1,const vector<Point> &h2,vector<Point> &h) {
    vector<Point>::const_iterator i=h1.begin(),j=h2.begin();
    int top=0;
    while(i!=h1.end()||j!=h2.end()){
        Point p=i==h1.end()?*j++:j==h2.end()?*i++:(*i<*j?*i++:*j++);  
        while(top>=2&&(h[top-1]-h[top-2])*(p-h[top-1])>=0) h.pop_back(),top--;
        h.push_back(p);top++;
    }
}
void Below_Merge(const vector<Point> &h1,const vector<Point> &h2,vector<Point> &h) {
    vector<Point>::const_iterator i=h1.begin(),j=h2.begin();
    int top=0;
    while(i!=h1.end()||j!=h2.end()){
       Point p=i==h1.end()?*j++:j==h2.end()?*i++:(*i<*j?*i++:*j++);    
        while(top>=2&&(h[top-1]-h[top-2])*(p-h[top-1])<=0) h.pop_back(),top--;
        h.push_back(p);top++;
    }
}
LL Trisection(const vector<Point> &h,const Point  &p) {
    int i,l=0,r=h.size()-1;
    while(r-l>2){
        int lmid=(l+l+r)/3,rmid=(r+l+r)/3;
        if((h[lmid]^p)>(h[rmid]^p)) r=rmid;
        else l=lmid;
    }
    LL ret=0xefefefefefefefefll;
    for(int i=l;i<=r;i++) ret=max(ret,h[i]^p);
    return ret;
}
struct Segtree{
    Segtree *ls,*rs;  
    vector<Point> cover,below;  
    void* operator new (size_t){
        static Segtree *mempool,*C;
        if(C==mempool)
            mempool=(C=new Segtree[1<<16])+(1<<16);
        C->ls=0x0;
        C->rs=0x0;
        return C++;
    }
    friend void Insert(Segtree *&p,int x,int y,int pos,const Point &point){
        int mid=x+y>>1;
        if(!p) p=new Segtree;
        if(x==y){
            p->cover.push_back(point);
            p->below.push_back(point);
            return ;
        }
        if(pos<=mid) Insert(p->ls,x,mid,pos,point);
        else  Insert(p->rs,mid+1,y,pos,point);
        if(pos==y){
            Cover_Merge(p->ls->cover,p->rs->cover,p->cover);
            Below_Merge(p->ls->below,p->rs->below,p->below);
        }
    }
    LL Get_Ans(int x,int y,int l,int r,const Point &point){
        int mid=x+y>>1;
        if(x==l&&y==r) return point.y>0?Trisection(cover,point):Trisection(below,point);
        if(r<=mid) return ls->Get_Ans(x,mid,l,r,point);
        if(l>mid) return rs->Get_Ans(mid+1,y,l,r,point);
        return max( ls->Get_Ans(x,mid,l,mid,point) , rs->Get_Ans(mid+1,y,mid+1,r,point) );
    }
}*tree = new Segtree;
#define Decode(x) ((x)^(Last_Ans&0x7fffffff))  
int main(){
    int i,x,y,l,r;
    char o[10];
    scanf("%d%s",&n,type);
    for(i=1;i<=n;i++){
        scanf("%s",o);
        if(o[0]=='A'){
            scanf("%d%d",&x,&y);  
            if(type[0]!='E')  
                x=Decode(x),y=Decode(y); 
            Point p(x,y);
            Insert(tree,1,n,++tot,p);
        }
        else{
            scanf("%d%d%d%d",&x,&y,&l,&r);
            if(type[0]!='E') x=Decode(x),y=Decode(y),l=Decode(l),r=Decode(r);
            Point p(x,y);
            #ifdef ONLINE_JUDGE
                printf("%lld\n",Last_Ans=tree->Get_Ans(1,n,l,r,p));
            #else
                printf("%I64d\n",Last_Ans=tree->Get_Ans(1,n,l,r,p));
            #endif
        }
    }           
    return 0;
}

C++友元函数(关键字:friend)
采用类的机制后实现了数据的隐藏与封装,类的数据成员一般定义为私有成员,成员函数一般定义为公有的,依此提供类与外界间的通信接口。但是,有时需要定义一些函数,这些函数不是类的一部分(注意友元函数不是类的一部分),但又需要频繁地访问类的数据成员,这时可以将这些函数定义为该函数的友元函数。除了友元函数外,还有友元类,两者统称为友元。友元的作用是提高了程序的运行效率(即减少了类型检查和安全性检查等都需要时间开销),但它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。*

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七情六欲·

学生党不容易~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值