http://www.elijahqi.win/archives/3114
题目描述
小Z发明了一套新的电影评分系统。这套系统有三种操作:发布新电影、对电影评分、以及询问电影评分的排名。具体是这样运作的:如果是发布新电影,并且这部电影的有所主演之前均没有出现过,那么这部新电影的评分为0,否则这部电影的评分为最近一部与该电影至少有一个共同主演的电影的评分;如果是对电影进行评分,那么这部电影的评分就变成之前评分与新的评分的平均数;如果是查询排名,则根据评分输出相应排名。评分最高的为第一名。如果有多部电影分数相同,那么输出最早的一部。电影的评分在0到5之间。
输入输出格式
输入格式:
输入的第一行是n,表示操作次数。接下来n行,每一行是以下三种操作之一:
Q x:查询当前排名为x的电影ID
R ID x actor1 actor2 …· actorx:发布新电影ID,该电影有x个主演分别为 actor1, actor2,…’
C ID score:评分操作,表示对电影ID的评分为 score
数据保证每个电影的ID不相同,且每部电影至多不超过5名主演。
1≤ actor1, actor2,··≤10^5
1≤ID≤10^5
输出格式:
对于每一个查询操作,输出相应排名的电影的ID。
输入输出样例
输入样例#1: 复制
10
R 1 1 1
R 2 2 1 2
C 2 2
R 3 1 2
Q 1
C 3 2
C 1 5
Q 1
Q 2
Q 3
输出样例#1: 复制
2
1
3
2
说明
样例解释
Movie 1 2 3
0 - -
0 0 -
0 1 -
0 1 1
Q 1 => 2 //Movie 2 wa s released be fore Movie 3
0 1 1.5
2.5 1 1.5
Q 1 => 1
Q 2 => 3
Q 3 => 2
数据范围
对于 30% 的数据,n ≤ 100
对于 100% 的数据,n ≤ 10000
将小数写成二进制位 用后缀平衡树模拟小数的比较过程
考虑这题的要求一定是取平均数那么也就是我每回/2 相当于将二进制下的小数整体向后面移动一位 然后再看整数部分是奇数还是偶数来判定我新加的一位是0还是1 那么就用sa表示我这个数的小数部分 fir表示我这一位是谁 然后sec表示我的后半部分是链接到哪个fir和sec组成的二元组上了 注意每次比较的时候需要先看一看原序列是否存在这样的高精度小数 然后再判断是否要新加入 对于在后缀平衡树上如何o(1)比较 那就是我需要记录一个标记 tag 若当前节点管辖范围是l~r那么他的标记是l+r>>1 他左区间的标记都会小于(l+r>>1) 右区间的标记都会大于(l+r>>1) 然后因为这个标记不好维护 所以每次修改的时候暴力重构即可 复杂度是对的
用一棵splay来存这个的整数部分 然后splay上的比较函数需要重新新写一个才可以
#include<cstdio>
#include<cctype>
#include<algorithm>
#define ll long long
using namespace std;
inline char gc(){
static char now[1<<16],*S,*T;
if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S)return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(!isdigit(ch)) {if (ch=='-') f=-1;ch=gc();}
while(isdigit(ch)) x=x*10+ch-'0',ch=gc();
return x*f;
}
const int N=1e5+100;
const int inf=0x3f3f3f3f;
int size[N],fa[N],c[N][2],n,num,cnt,v[N],tim[N],flag,root;
int lc[N],rc[N],fir[N],sec[N],sa[N],rd[N],last[N],rt;int tag[N];
inline void update(int x){
size[x]=size[c[x][0]]+size[c[x][1]]+1;
}
inline void rotate(int x,int &tar){
int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1;
if (y==tar) tar=x;else c[z][c[z][1]==y]=x;
fa[c[x][r]]=y;fa[y]=x;fa[x]=z;
c[y][l]=c[x][r];c[x][r]=y;update(y);update(x);
}
inline void splay(int x,int &tar){
while(x!=tar){
int y=fa[x],z=fa[y];
if (y!=tar){
if (c[y][0]==x^c[z][0]==y) rotate(x,tar);else rotate(y,tar);
}rotate(x,tar);
}
}
inline bool check(int id1,int id2){
if (v[id1]>v[id2]) return 1;if (v[id1]<v[id2]) return 0;
if (tag[sa[id1]]>tag[sa[id2]]) return 1;
if (tag[sa[id1]]<tag[sa[id2]]) return 0;
return tim[id1]<tim[id2];
}
inline void insert1(int &x,int id,int f){
if (!x) {x=id;fa[x]=f;size[x]=1;splay(x,root);return;}
if (check(id,x)) insert1(c[x][0],id,x);else insert1(c[x][1],id,x);
}
inline int find(int x,int k){
int l=c[x][0],r=c[x][1];
if (size[l]+1==k) return x;
if (k<=size[l]) return find(l,k);else return find(r,k-size[l]-1);
}
inline void del(int x){
splay(x,root);static int pre,succ;
if (c[x][1]*c[x][0]==0){
root=c[x][1]+c[x][0];if (c[x][1]) c[x][1]=0;
if (c[x][0]) c[x][0]=0;fa[root]=0;return;
}
pre=c[x][0],succ=c[x][1];
while(c[pre][1]) pre=c[pre][1];
while(c[succ][0]) succ=c[succ][0];
splay(succ,root);splay(pre,c[succ][0]);
c[pre][1]=fa[c[pre][1]]=0;update(pre);update(root);
}
inline void rebuild(int x,int l,int r){
int mid=l+r>>1;if (lc[x]) rebuild(lc[x],l,mid);
if (rc[x]) rebuild(rc[x],mid+1,r);tag[x]=l+r>>1;
}
inline void lrotate(int &x,int L,int R){
int r=rc[x];rc[x]=lc[r];lc[r]=x;x=r;rebuild(x,L,R);
}
inline void rrotate(int &x,ll L,ll R){
int l=lc[x];lc[x]=rc[l];rc[l]=x;x=l;rebuild(x,L,R);
}
inline int check1(int id1,int id2){
if (fir[id1]>fir[id2]) return 0;if (fir[id1]<fir[id2]) return 1;
if (tag[sec[id1]]>tag[sec[id2]]) return 0;if (tag[sec[id1]]<tag[sec[id2]]) return 1;
return 2;
}
inline void insert2(int &x,int l,int r){
if (!x) {x=num;rd[x]=rand();lc[x]=rc[x]=0;tag[x]=l+r>>1;return;}
if(check1(num,x)==2) {flag=x;return;}
int mid=l+r>>1;
if (check1(num,x)) {
insert2(lc[x],l,mid);
if(rd[lc[x]]>rd[x]) rrotate(x,l,r);return;
}insert2(rc[x],mid+1,r);
if (rd[rc[x]]>rd[x]) lrotate(x,l,r);
}
inline void print(int x){
if (!x) return;
if (c[x][0]) print(c[x][0]);
printf("%d %d %lld\n",x,v[x],tag[sa[x]]);
if (c[x][1]) print(c[x][1]);
}
inline void print1(int x){
if (!x) return;
printf("%d ",fir[x]);print1(sec[x]);
}
int main(){
freopen("bzoj5159.in","r",stdin);
// freopen("bzoj5159.out","w",stdout);
n=read();srand(20010820);
for (int ii=1;ii<=n;++ii){static int x,nm,now,act;
char ch=gc();while(ch!='Q'&&ch!='C'&&ch!='R') ch=gc();//print(root);puts("---");
if (ch=='Q'){printf("%d\n",find(root,read()));continue;}
if (ch=='R'){
x=read();nm=read();now=0;
for (int i=1;i<=nm;++i){
act=read();if (tim[last[act]]>tim[now]) now=last[act];last[act]=x;
}v[x]=v[now];sa[x]=sa[now];tim[x]=++cnt;insert1(root,x,root);continue;
}
if (ch=='C'){
x=read();nm=read();del(x);v[x]+=nm;
if (sa[x]||v[x]&1){
fir[++num]=v[x]&1;sec[num]=sa[x];// sec link to sa
sa[x]=num;//print1(sa[x]);puts("decimal");
flag=0;insert2(rt,1,inf);if (flag) --num,sa[x]=flag;
// if (x==73611) print1(sa[7213]),puts("decimal");
}v[x]>>=1;insert1(root,x,root);//print(root);
}
}
return 0;
}