您的位置:首页 > 其它

UOJ#349:【WC2018】即时战略 (LCT)

2018-03-02 16:22 316 查看
题目传送门:http://uoj.ac/problem/349

题目分析:WC评讲的时候就发现自己制杖,连LCT能动态链剖都忘了QAQ。

然后这个万年大坑今天终于被我填上了。

然后我在被UOJ过不了Extra test#3,被卡询问次数。改了很久都过不了,我索性弃疗了。(这绝对是场阴谋,逼我写替罪羊树维护动态点分树!)

LCT维护前驱后继,可以通过在Splay上记子树中最左最右实现。

扔个code上来就走。

CODE:

// RTS sample program

#include "rts.h"

#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<stdio.h>
#include<algorithm>
#include<set>
using namespace std;

const int maxn=300100;

const long long M1=998244353;
const long long M2=1000000007;
const long long M3=1004535809;
typedef long long LL;
LL seed=0;

bool vis[maxn];
set <int> a,b;

struct Tnode
{
int val,Left,Right,path_parent;
bool flip;
Tnode *son[2],*fa;

int Get_d() { return (fa->son[1]==this); }
void Connect(Tnode *P,int d) { (son[d]=P)->fa=this; }

int Prev() { if (son[0]) return son[0]->Right; else return 0; }
int Succ() { if (son[1]) return son[1]->Left; else return 0; }

void Up()
{
Left=Right=val;
if (son[0]) Left=son[0]->Left;
if (son[1]) Right=son[1]->Right;
}
void Push_down()
{
if (flip)
{
swap(son[0],son[1]);
if (son[0]) son[0]->flip^=1,swap(son[0]->Left,son[0]->Right);
if (son[1]) son[1]->flip^=1,swap(son[1]->Left,son[1]->Right);
flip=false;
}
}
} tree[maxn];
Tnode *Node[maxn];
int cur=-1;

int Rand()
{
seed=(seed*M1+M2)%M3;
return (int)seed;
}

int Get(int n)
{
int x=Rand()%n+1;
set <int> :: iterator p=a.lower_bound(x);
if (p==a.end()) p--;
return (*p);
}

void Solve1(int n)
{
int c[2];
c[0]=c[1]=1;
while (!a.empty())
{
int i=Get(n);
int x=Rand()&1,now=explore(c[x],i);
if (vis[now]) x=(!x),now=explore(c[x],i);
vis[now]=true;
a.erase(now);
while (now!=i) now=explore(now,i),vis[now]=true,a.erase(now);
c[x]=i;
}
}

Tnode *New_node(int v)
{
cur++;
tree[cur].val=tree[cur].Left=tree[cur].Right=v;
tree[cur].path_parent=0;
tree[cur].flip=false;
tree[cur].fa=tree[cur].son[0]=tree[cur].son[1]=NULL;
return tree+cur;
}

void Push(Tnode *P)
{
if (!P) return;
Push(P->fa);
P->Push_down();
}

void Zig(Tnode *P)
{
Tnode *F=P->fa;
int d=P->Get_d();
if (P->son[!d]) F->Connect(P->son[!d],d);
else F->son[d]=NULL;
if (F->fa) F->fa->Connect(P, F->Get_d() );
else P->fa=NULL;
P->Connect(F,!d);
F->Up();
P->path_parent=F->path_parent;
F->path_parent=0;
}

void Splay(Tnode *P)
{
Push(P);
Tnode *F;
while (P->fa)
{
F=P->fa;
if (F->fa) ( P->Get_d()^F->Get_d() )? Zig(P):Zig(F);
Zig(P);
}
P->Up();
}

/*int Get1(int n)
{
int x=Rand()%n+1;
set <int> :: iterator p=b.lower_bound(x);
if (p==b.en
f0c2
d()) p--;
return (*p);
}*/

void Down(int x)
{
Splay(Node[x]);
Tnode *&tag=Node[x]->son[1];
if (tag)
{
tag->fa=NULL;
tag->path_parent=x;
tag=NULL;
Node[x]->Up();
}
}

void Access(int x)
{
Down(x);
int y=Node[x]->path_parent;
while (y)
{
Down(y);
Node[y]->Connect(Node[x],1);
Node[x]->path_parent=0;
Node[y]->Up();
x=y;
y=Node[x]->path_parent;
}
}

void Solve2(int n)
{
//b.clear();
//b.insert(1);
for (int i=1; i<=n; i++) Node[i]=New_node(i);
while (!a.empty())
{
int i=Get(n);
int now=1,last=0;
while (vis[now])
{
Splay(Node[now]);
while (1)
{
Node[now]->Push_down();
int Next=explore(now,i);
if (Next==Node[now]->Prev()) now=Node[now]->son[0]->val;
else
if (Next==Node[now]->Succ()) now=Node[now]->son[1]->val;
else
{
last=now;
now=Next;
break;
}
}
}

while (now!=i)
{
Node[now]->path_parent=last;
a.erase(now);
//b.insert(now);
vis[now]=true;
last=now;
now=explore(last,i);
}
Node[now]->path_parent=last;
a.erase(now);
//b.insert(now);
vis[now]=true;
Access(now);
}
}

void play(int n, int T, int dataType) {
a.clear();
for (int i=2; i<=n; i++) a.insert(i);
for (int i=1; i<=n; i++) vis[i]=false;
vis[1]=true;

if (dataType==3) Solve1(n);
else Solve2(n);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: