3600: 没有人的算术
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1118 Solved: 452
[ Submit][ Status][ Discuss]
Description
Input
Output
Sample Input
Sample Output
HINT
Source
。。。。神。。神题。。。
具体过程太抽象了。。。我们考虑如果能有一种方法能快速得到排名那就方便多了
考虑用一个平衡树维护排名,
用实数表示排名,对于每一个平衡树上的节点,用这个节点的所属实数区间的中位数作为排名;对于实数区间(根的实数区间自己定),对于右儿子,区间为(mid,r),左儿子区间为(l,mid)
每个节点在保存实数排名的同时,也要保存之前赋值的(l,r)(注意是保存l、r,而不是l、r的实数排名)
然后插入时只需要做平衡树的普通插入即可,
询问用一个线段树维护,每个节点存最大值的下标(即答案)
对于平衡树的选择,因为实数区间要相对静止,所以考虑用替罪羊树
有一个小技巧:可以维护一个id数组表示每个原数组位置现在对应的是替罪羊树上的哪个节点,从而来避免替罪羊树的删除操作(同时也是为了维护相对静止),然后线段树在比较的时候就是比较id的实数排名就好了
PS.我这个板子好像跑很快?
代码:
#include<queue>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
#include<cstdlib>
using namespace std;
typedef long long LL;
typedef double DL;
const int INF = 20011209;
const int maxn = 500010;
DL f[maxn];
struct data{
int x,y;
data(int _x = 0,int _y = 0){x = _x; y = _y;}
bool operator == (const data &b) const
{
return f[x] == f[b.x] && f[y] == f[b.y];
}
bool operator < (const data &b) const
{
return f[x] < f[b.x] || (f[x] == f[b.x] && f[y] < f[b.y]);
}
bool operator > (const data &b) const
{
return f[x] > f[b.x] || (f[x] == f[b.x] && f[y] > f[b.y]);
}
}val[maxn];
int n,m,rt,cnt;
int cur[maxn],id[maxn];
int siz[maxn],ch[maxn][2],tot;
int stk[maxn],now,p;
inline LL getint()
{
LL ret = 0,f = 1;
char c = getchar();
while (c < '0' || c > '9')
{
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
ret = ret * 10 + c - '0',c = getchar();
return ret * f;
}
inline bool bal(int o)
{
return max(siz[ch[o][1]],siz[ch[o][0]]) <= 0.77 * siz[o];
}
inline void maintain(int o)
{
siz[o] = siz[ch[o][1]] + siz[ch[o][0]] + 1;
}
inline void dfs(int o)
{
if (!o) return;
dfs(ch[o][0]);
stk[++now] = o;
dfs(ch[o][1]);
}
inline void rebuild(int &o,int l,int r,DL xl,DL xr)
{
if (l > r) return;
int mid = l + r >> 1;
o = stk[mid]; siz[o] = 1; f[o] = (xl + xr) / 2;
ch[o][0] = ch[o][1] = 0;
if (l == r) return;
rebuild(ch[o][0],l,mid - 1,xl,(xl + xr) / 2);
rebuild(ch[o][1],mid + 1,r,(xl + xr) / 2,xr);
maintain(o);
return;
}
inline void Rebuild(int &p,DL L,DL R)
{
dfs(p);
rebuild(p,1,now,L,R);
now = 0;
}
inline int insert(int &o,DL l,DL r,data x)
{
if (!o) {val[o = ++tot] = x; f[o] = (l + r) / 2.0; maintain(o);}
if (x == val[o]) return o;
int d = x > val[o],ret = 0;
if (!d) ret = insert(ch[o][d],l,(l + r) / 2.0,x);
else ret = insert(ch[o][d],(l + r) / 2.0,r,x);
maintain(o);
if (!bal(o)) Rebuild(o,l,r);
return ret;
}
inline int idmax(int a,int b)
{
return f[cur[a]] >= f[cur[b]] ? a : b;
}
inline void update(int o,int l,int r,int pos)
{
if (l == r) {id[o] = l; return;}
int mid = l + r >> 1,lc = o << 1,rc = o << 1 | 1;
if (pos <= mid) update(lc,l,mid,pos);
else update(rc,mid + 1,r,pos);
id[o] = idmax(id[lc],id[rc]);
}
inline int query(int o,int l,int r,int al,int ar)
{
if (al <= l && r <= ar) return id[o];
int ret = 0,mid = l + r >> 1,lc = o << 1,rc = o << 1 | 1;
if (al <= mid) ret = idmax(ret,query(lc,l,mid,al,ar));
if (mid < ar) ret = idmax(ret,query(rc,mid + 1,r,al,ar));
return ret;
}
inline char getcom()
{
char c = getchar();
while (c != 'Q' && c != 'C') c = getchar();
return c;
}
int main()
{
n = getint(); m = getint();
f[rt = ++tot] = (0 + INF) / 2.0;
val[rt] = (data){0,INF};
siz[tot] = 1;
f[0] = -1;
for (int i = 1; i <= n; i++) update(1,1,n,i);
for (int i = 1; i <= n; i++) cur[i] = 1;
for (int i = 1; i <= m; i++)
{
char c = getcom();
int l = getint(),r = getint();
if (c == 'Q') printf("%d\n",query(1,1,n,l,r));
else
{
int k = getint();
cur[k] = insert(rt,0,INF,(data){cur[l],cur[r]});
update(1,1,n,k);
}
return 0;
}