BZOJ3533 SDOI2014 向量集

来源:互联网 发布:淘宝主图制作技巧 编辑:程序博客网 时间:2024/06/05 05:15

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

原创粉丝点击