zoukankan      html  css  js  c++  java
  • BZOJ 3533: [Sdoi2014]向量集( 线段树 + 三分 )

    答案一定是在凸壳上的(y>0上凸壳, y<0下凸壳). 线段树维护, 至多N次询问, 每次询问影响O(logN)数量级的线段树结点, 每个结点O(logN)暴力建凸壳, 然后O(logN)三分(二分也是可以的, 不过三分好写, 而且没精度问题....), O(Nlog^2N), 可以AC。

    --------------------------------------------------------------------------------------------

    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<algorithm>
     
    using namespace std;
     
    typedef long long ll;
    #define Decode(x) (x ^= (ans & 0X7FFFFFFF))
     
    const int maxn = 400009;
     
    bool Online;
    int n, N, L, R, pos;
    ll ans;
     
    inline void Max(ll &x, ll t) {
    if(t > x) x = t;
    }
     
    inline int getint() {
    char c = getchar();
    int ret = 0, f = 1;
    for(; !isdigit(c); c = getchar())
    if(c == '-') f = 0;
    for(; isdigit(c); c = getchar())
    ret = ret * 10 + c - '0';
    return f ? ret : -ret;
    }
     
    struct P {
    int x, y;
    bool operator < (const P &o) const {
    return x < o.x;
    }
    ll operator * (const P &o) const {
    return ll(x) * o.x + ll(y) * o.y;
    }
    } p[maxn], o[maxn], seq[4000000], q;
     
    struct Node {
    Node *lc, *rc;
    int l[2], r[2], t;
    } pool[maxn << 1], *pt = pool, *Root;
     
    void Build(Node* t, int l, int r) {
    t->t = 0;
    if(l != r) {
    int m = (l + r) >> 1;
    Build(t->lc = pt++, l, m);
    Build(t->rc = pt++, m + 1, r);
    }
    }
     
    inline bool chk(P &a, P &b, P &c, int t) {
    int e = a.y - b.y, f = a.x - b.x, g = b.y - c.y, h = b.x - c.x;
    if(h < 0) t ^= 1;
    if(f < 0) t ^= 1;
    return t ? ll(e) * h >= ll(f) * g : ll(e) * h <= ll(f) * g;
    }
     
    void ConvexHull(Node* t, int l, int r, int v) {
    int len = 0, &Left = t->l[v];
    for(int i = l; i <= r; i++) o[len++] = p[i];
    sort(o, o + len);
    seq[Left = pos] = o[0];
    for(int i = 1; i < len; i++) {
    if(seq[pos].x == o[i].x) {
    if(!v && seq[pos].y >= o[i].y) continue;
    if(v && seq[pos].y <= o[i].y) continue;
    pos--;
    }
    while(pos > Left && chk(seq[pos - 1], seq[pos], o[i], v))
    pos--;
    seq[++pos] = o[i];
    }
    t->r[v] = pos++;
    }
     
    void Query(Node* t, int l, int r) {
    if(L <= l && r <= R) {
    if(!t->t) {
    ConvexHull(t, l, r, 0);
    ConvexHull(t, l, r, 1);
    t->t = 1;
    }
    int Left = t->l[q.y < 0], Right = t->r[q.y < 0];
    if(!q.y) {
    Max(ans, max(seq[Left] * q, seq[Right] * q));
    return;
    }
    while(Left <= Right) {
    int d = (Right - Left) / 3, m1 = Left + d, m2 = Right - d;
    Max(ans, max(seq[m1] * q, seq[m2] * q));
    if(seq[m1] * q < seq[m2] * q) {
    Left = m1 + 1;
    } else
    Right = m2 - 1;
    }
    } else {
    int m = (l + r) >> 1;
    if(L <= m) Query(t->lc, l, m);
    if(m < R) Query(t->rc, m + 1, r);
    }
    }
     
    void Init() {
    N = getint();
    char c;
    scanf(" %c", &c);
    Online = (c != 'E');
    Build(Root = pt++, 1, N);
    }
     
    void Work() {
    char c;
    n = pos = 0, ans = 0;
    for(int i = 0; i < N; i++) {
    scanf(" %c", &c);
    if(c != 'A') {
    q.x = getint(), q.y = getint();
    L = getint(), R = getint();
    if(Online) {
    Decode(q.x), Decode(q.y);
    Decode(L), Decode(R);
    }
    ans = -1LL << 60;
    Query(Root, 1, N);
    printf("%lld ", ans);
    } else {
    ++n;
    p[n].x = getint(), p[n].y = getint();
    if(Online)
    Decode(p[n].x), Decode(p[n].y);
    }
    }
    }
     
    int main() {
    Init();
    Work();
    return 0;
    }

    --------------------------------------------------------------------------------------------

    3533: [Sdoi2014]向量集

    Time Limit: 25 Sec  Memory Limit: 512 MB
    Submit: 495  Solved: 164
    [Submit][Status][Discuss]

    Description

    维护一个向量集合,在线支持以下操作:
    "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

    Source

  • 相关阅读:
    转: IOS程序内发短信 MFMessageComposeViewController
    对象之间如何比较是否相等?
    相比xib 使用代码编排view 的一个明显的好处就是可以更好地重复使用已有代码,减少代码冗余。
    关于deselectRowAtIndexPath
    IOS中为tableViewCell增加右侧标记(选中或者更多)
    ios 中是否每一个对象(尤其是在使用多线程时),都要判断一下对象是否为nil,以防止程序闪退?
    模拟出ios中流行的黑色背景底
    转 ios给view设置圆角
    转 UIAlertView 不显示、屏幕变灰
    转 UIActivityIndicatorView、UIProgressView 活动与进度指示器-IOS开发
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/5174067.html
Copyright © 2011-2022 走看看