Points 【CodeForces - 19D】【线段树+思维+离散化】

版权声明:https://blog.csdn.net/qq_41730082 https://blog.csdn.net/qq_41730082/article/details/88204248

题目链接


  好题!至少在线段树上面又有了新的想法。

  一开始的做法是写了Splay树,然后答案就是找合法后继,但是时间复杂度略高(TLE在第30组)——后面有相应的代码附上(想看的可以看一下哦,当作学习Splay还是不错的),之后就是一直在不断的进行优化,然后过程之中,想到了既然要维护二维图上符合这个条件的下一个节点,不妨就去离散化,然后去寻找这样的符合条件的节点。

  这么应该怎么去写,一开始的Splay倒是给了我一点思想,当时造出来的一组数据提点到了我,我们既然要找下一个符合条件的点,要满足x、y均要强制大于它,所以我们似乎可以去建一棵线段树来维护,怎么维护呢?就是要用到了set的一些性质,我们去得到每个数的其中的最大的y的坐标维护进线段树中,然后我们所要找的[l, r]的区间,就只要去维护x的关系就行了,需要满足的是r > x并且还有该段区间的val > y这两个条件即可。

  首先建树,然后维护区间最大值。


测试样例:

10
a 1 4
a 2 3
a 3 5
a 3 7
f 1 4
f 1 2
r 3 5
a 4 3
f 1 4
f 3 2
Output:
3 5
2 3
3 7
4 3

AC代码:线段树

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 2e5 + 7;
int N, lisn[maxN], tot, diff, tree[maxN<<2];
set<int> st[maxN];
struct Ques
{
    char op[10];
    int x, y;
}q[maxN];
void buildTree(int rt, int l, int r)
{
    tree[rt] = -1;
    if(l == r) return;
    int mid = HalF;
    buildTree(Lson);
    buildTree(Rson);
}
void update(int rt, int l, int r, int qx)
{
    if(l == r)
    {
        if(st[qx].size()) tree[rt] = *(-- st[qx].end());
        else tree[rt] = -1;
        return;
    }
    int mid = HalF;
    if(qx <= mid) update(Lson, qx);
    else update(Rson, qx);
    tree[rt] = max(tree[lsn], tree[rsn]);
}
int query(int rt, int l, int r, int qx, int qy)
{
    if(r <= qx || tree[rt] <= qy) return -1;
    if(l == r) return l;
    int mid = HalF;
    int ans = query(Lson, qx, qy);
    if(ans == -1) ans = query(Rson, qx, qy);
    return ans;
}
inline void init()
{
    tot = 0;
}
int main()
{
    scanf("%d", &N);
    init();
    for(int i=1; i<=N; i++)
    {
        scanf("%s%d%d", q[i].op, &q[i].x, &q[i].y);
        lisn[++tot] = q[i].x;
    }
    sort(lisn + 1, lisn + tot + 1);
    diff = (int)( unique(lisn + 1, lisn + tot + 1) - lisn - 1 );
    buildTree(1, 1, diff);
    for(int i=1, x, y, ans; i<=N; i++)
    {
        x = (int)(lower_bound(lisn + 1, lisn + diff + 1, q[i].x) - lisn);
        y = q[i].y;
        if(q[i].op[0] == 'a')
        {
            st[x].insert(y);
            update(1, 1, diff, x);
        }
        else if(q[i].op[0] == 'r')
        {
            st[x].erase(y);
            update(1, 1, diff, x);
        }
        else
        {
            ans = query(1, 1, diff, x, y);
            if(ans ^ -1) printf("%d %d\n", lisn[ans], *st[ans].upper_bound(y));
            else printf("-1\n");
        }
    }
    return 0;
}

TLE代码:又长又复杂但是想了我好久的Splay。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 2e5 + 7;
int N, l_x[maxN], l_y[maxN], t_x, t_y, dx, dy, root, cnt;
set<int> st[maxN<<1];
set<int>::iterator it;
struct Ques
{
    char op[10];
    int x, y;
}q[maxN];
struct node
{
    int ff, val, cnt, size, ch[2];
    node() { ff = val = cnt = size = ch[0] = ch[1] = 0; }
    void init(int fa, int _val) { ff = fa; val = _val; cnt = size = 1; ch[0] = ch[1] = 0; }
}t[maxN<<3];
void pushup(int rt) { t[rt].size = t[t[rt].ch[0]].size + t[t[rt].ch[1]].size + t[rt].cnt; }
void Rotate(int x)
{
    int y = t[x].ff, z = t[y].ff;
    int k = t[y].ch[1] == x;
    t[z].ch[t[z].ch[1] == y] = x;
    t[x].ff = z;
    t[y].ch[k] = t[x].ch[k^1];
    t[t[x].ch[k^1]].ff = y;
    t[x].ch[k^1] = y;
    t[y].ff = x;
    pushup(y);  pushup(x);
}
void Splay(int x, int goal)
{
    while(t[x].ff != goal)
    {
        int y = t[x].ff, z = t[y].ff;
        if(z != goal) (t[z].ch[0] == y) ^ (t[y].ch[0] == x) ? Rotate(x) : Rotate(y);
        Rotate(x);
    }
    if(!goal) root = x;
}
void insert(int x)
{
    int u = root, ff = 0;
    while(u && t[u].val != x)
    {
        ff = u;
        u = t[u].ch[x > t[u].val];
    }
    if(u) t[u].cnt++;
    else
    {
        u = ++cnt;
        if(ff) t[ff].ch[x > t[ff].val] = u;
        t[u].init(ff, x);
    }
    Splay(u, 0);
}
void Find(int x)
{
    int u = root;
    if(!u) return;
    while(t[u].ch[x > t[u].val] && x != t[u].val) u = t[u].ch[x > t[u].val];
    Splay(u, 0);
}
int Next(int x, int f)
{
    Find(x);
    int u = root;
    if(t[u].val > x && f) return u;
    if(t[u].val < x && !f) return u;
    u = t[u].ch[f];
    while(t[u].ch[f^1]) u = t[u].ch[f^1];
    return u;
}
void Delet(int x)
{
    int last = Next(x, 0), next = Next(x, 1);
    Splay(last, 0); Splay(next, last);
    int del = t[next].ch[0];
    if(t[del].cnt > 1) { t[del].cnt--; Splay(del, 0); }
    else t[next].ch[0] = 0;
}
inline void init()
{
    t_x = t_y = root = cnt = 0;
    insert(INF);
    insert(-INF);
}
int main()
{
    scanf("%d", &N);
    init();
    for(int i=1; i<=N; i++)
    {
        scanf("%s%d%d", q[i].op, &q[i].x, &q[i].y);
        l_x[++t_x] = q[i].x;   l_y[++t_y] = q[i].y;
    }
    sort(l_x + 1, l_x + t_x + 1);
    sort(l_y + 1, l_y + t_y + 1);
    dx = (int)( unique(l_x + 1, l_x + t_x + 1) - l_x - 1 );
    dy = (int)( unique(l_y + 1, l_y + t_y + 1) - l_y - 1 );
    for(int i=1, x, y; i<=N; i++)
    {
        x = (int)( lower_bound(l_x + 1, l_x + dx + 1, q[i].x) - l_x );
        y = (int)( lower_bound(l_y + 1, l_y + dy + 1, q[i].y) - l_y );
        if(q[i].op[0] == 'a')   //add
        {
            insert(x);
            st[x].insert(y);
        }
        else if(q[i].op[0] == 'r')  //remove
        {
            st[x].erase(y);
            Delet(x);
        }
        else    //find
        {
            while(true)
            {
                int nex = Next(x, 1), tmp = t[nex].val;
                if(tmp == INF) { printf("-1\n"); break; }
                it = st[tmp].upper_bound(y);
                if(it == st[tmp].end()) { x = tmp; continue; }
                printf("%d %d\n", l_x[tmp], l_y[*it]);
                break;
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41730082/article/details/88204248