May 16 race cattle off white stone sister or half segment tree

Off white cow race 16 months

 

After I read this topic about AC solution to a problem people are basically tree line, but half also available.

The subject is natural to want to be sure of one sort, and then deal with the other side then drained order, discrete remember the other side.

How to deal with it, you think about it, look for the law can be found, in fact, we are looking for increasing subsequence.

The first is the importance of the find is my sister 1, and then remove these elements continue to look for a second time, the second is to find the degree of importance for the two sister.

So every point, as long as we judge according to its size it should be put in the position (as far forward, and less than this number), and then update the position, then return to this position, its location is its degree of importance .

 

emmm fact, is to use an array, each array location i memory is of importance to the current position of the maximum value i.

Specific look at the code.

 

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
#include <string>
#include <iostream>
#include <map>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn = 2e5 + 10;
typedef long long ll;
int num[maxn];
map<ll, ll>mp;
struct node
{
    int l, r;
    int sum;
}tree[4*maxn];
struct edge
{
    ll a, b, id, num, ans;
}ex[maxn];

bool cmp(edge a,edge b)
{
    return a.a > b.a;
}

bool cmp1(edge a,edge b)
{
    return a.b < b.b;
}

bool cmp2(edge a,edge b)
{
    return a.id < b.id;
}

int tot = 0;
int ok(ll x)
{
    if (x > num[1]) return 1;
    if (x < num[tot])
    {
        tot++;
        return tot;
    }
    int l = 1, r = tot, ans = 0;
    int mid = (l + r) >> 1;
    while (l <= r) {
        int mid = (l + r) / 2;
        if (num[mid]<x) ans = mid, r = mid - 1;
        else l = mid + 1;
    }
    return ans;
}

int main()
{
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%lld%lld", &ex[i].a, &ex[i].b), ex[i].id = i;
    }
    sort(ex + 1, ex + 1 + n, cmp1);
    for (int i = 1; i <= n; i++) mp[ex[i].b] = i;
    sort(ex + 1, ex + 1 + n, cmp);
    num[1] = mp[ex[1].b];
    ex[1].ans = 1;
    tot = 1;
    for(int i=2;i<=n;i++)
    {
        int f = ok(mp[ex[i].b]);
        // printf("%lld ex[%d]=%lld f=%d\n",mp[ex[i].b], i, ex[i].b, f);
        num[f] = mp[ex[i].b];
        ex[i].ans = f;
    }
    sort(ex + 1, ex + 1 + n, cmp2);
    for (int i = 1; i <= n; i++) printf("%lld\n", ex[i].ans);
    return 0;
}
Bipartite

 

Methods segment tree online and I feel a bit like the reverse order, that is, first and foremost, b discrete, then a sort,

Then traverse from 1 ~ n, if b is first determined for each of b ~ n has no value, in fact, there is no large spare b than the front again, go to the maximum available, the degree of importance is the maximum value +1 (this is because the deposit into is the maximum)

No less important is the degree 1, and then update the point b to b of the importance of the tree into segments b this position in order to query the back.

This well written.

 

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
#include <string>
#include <iostream>
#include <map>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn = 2e5 + 10;
typedef long long ll;
map<ll, ll>mp;
struct node
{
    int l, r;
    int num;
}tree[4*maxn];
struct edge
{
    ll a, b, id, num, ans;
}ex[maxn];

bool cmp(edge a,edge b)
{
    return a.a > b.a;
}

bool cmp1(edge a,edge b)
{
    return a.b < b.b;
}

bool cmp2(edge a,edge b)
{
    return a.id < b.id;
}

void build(int id, int l, int r) {
    tree[id].l = l;
    tree[id].r = r;
    if (l == r) {
        tree[id].num = 0;
        return;
    }
    int mid = (l + r) >> 1;
    build(id << 1, l, mid);
    build(id << 1 | 1, mid + 1, r);
}

int query(int id, int x, int y) {
    int l = tree[id].l;
    int r = tree[id].r;
    if (x <= l && y >= r) {
        //    printf("id=%d sum=%d \n", id,tree[id].sum);
        return tree[id].num;
    }
    int ans = 0;
    int mid = (l + r) >> 1;
    if (x <= mid) ans = max(ans, query(id << 1, x, y));
    if (y > mid) ans = max(ans, query(id << 1 | 1, x, y));
    //    printf("id=%d ans=%d l=%d r=%d x=%d y=%d \n", id, ans, l, r,x,y);
    return ans;
}

void push_up(int id) {
    tree[id].num = max(tree[id << 1].num , tree[id << 1 | 1].num);
}

void update(int id, int x,int val) {
    int l = tree[id].l;
    int r = tree[id].r;
    if (l == r) {
        tree[id].num = val;
        return;
    }
    int mid = (l + r) >> 1;
    if (x <= mid) update(id << 1, x,val);
    else update(id << 1 | 1, x,val);
    push_up(id);
}


int main()
{
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%lld%lld", &ex[i].a, &ex[i].b), ex[i].id = i;
    }
    sort(ex + 1, ex + 1 + n, cmp1);
    for (int i = 1; i <= n; i++) mp[ex[i].b] = i;
    sort(ex + 1, ex + 1 + n, cmp);
    build(1, 1, n);
    for(int i=1;i<=n;i++)
    {
        int f = query(1, mp[ex[i].b], n) + 1;
        ex[i].ans = f;
        update(1, mp[ex[i].b],f);
    }
    sort(ex + 1, ex + 1 + n, cmp2);
    for (int i = 1; i <= n; i++) printf("%lld\n", ex[i].ans);
    return 0;
}
To reverse segment tree

 

Guess you like

Origin www.cnblogs.com/EchoZQN/p/11201051.html