bzoj 4391: [Usaco2015 dec]High Card Low Card Segment Tree

meaning of the title

Dairy cows Bessie and Elsie are playing a card game. A total of 2N cards, points are 1 to 2N, each cow will be divided into N cards.
The game is divided into N rounds, because Bessie is so smart that she can even predict what Elsie will play in each round.
In each round of the game, two bulls each play a card, and the winner of the big points wins.
At the same time, Bessie had a chance to choose a certain time point, and from that time on, those with fewer points in each round won.
Bessie now wonders how many rounds can he win at most?
2≤N≤50,000

Analysis

It is not difficult to find that the best case is to use the largest T card before the time point t.
If we enumerate the time points, all we need to do now is add a card to each collection at a time, and then maintain the maximum number of rounds that can be won.
Greedily, if you want to win the most times, then it must be to match each card with the biggest card you can win at present, if not, regardless.
So just use the segment tree to maintain, let the left and right intervals match themselves, and then the extra ones match each other.
It's not hard to find that this can be modified by O(logn), and then it's done.

Code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

const int N=50005;

int n,a[N],b[N],ans[N];
bool vis[N*2];
struct tree{int s1,s2;}t[N*8];

void build(int d,int l,int r)
{
    t[d].s1=t[d].s2=0;
    if (l==r) return;
    int mid=(l+r)/2;
    build(d*2,l,mid);build(d*2+1,mid+1,r);
}

void updata(int d,int op)
{
    int s=!op?min(t[d*2+1].s1,t[d*2].s2):min(t[d*2].s1,t[d*2+1].s2);
    t[d].s1=t[d*2].s1+t[d*2+1].s1-s;
    t[d].s2=t[d*2].s2+t[d*2+1].s2-s;
}

void ins(int d,int l,int r,int x,int op)
{
    if (l==r)
    {
        if (vis[l]) t[d].s2=1;
        else t[d].s1=1;
        return;
    }
    int mid=(l+r)/2;
    if (x<=mid) ins(d*2,l,mid,x,op);
    else ins(d*2+1,mid+1,r,x,op);
    updata(d,op);
}

int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%d",&b[i]),vis[b[i]]=1;
    for (int i=n*2,tot=0;i>=1;i--) if (!vis[i]) a[++tot]=i;
    for (int i=1;i<=n;i++) ins(1,1,n*2,a[i],0),ins(1,1,n*2,b[i],0),ans[i]+=i-t[1].s1;
    build(1,1,n*2);
    for (int i=n;i>=1;i--) ins(1,1,n*2,a[i],1),ins(1,1,n*2,b[i],1),ans[i-1]+=n-i+1-t[1].s1;
    int mx=0;
    for (int i=0;i<=n;i++) mx=max(mx,ans[i]);
    printf("%d",mx);
    return 0;
}

Posted by gli on Tue, 05 Feb 2019 21:24:16 -0800