bzoj1056(挖个坑wa+tle,平衡树)

10 篇文章 0 订阅

2016.8.22:这坑已经放弃填了。。。。。。。。。。。

代码题。。。

虽然还没有过,但是有学了一些经验

1、中间就可以直接普通的输入输出了

freopen("rank.in","r",stdin);
freopen("rank.out","w",stdout);<pre name="code" class="cpp"><span style="white-space:pre">	</span>                                          <span style="white-space:pre">													</span>  fclose(stdin);
fclose(stdout);

 2、发觉读题太关键了,这道题想当然的读错好几遍题。。。 

3、注意样例,必须要先读懂样例才可以,样例给了很多的信息

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#define debug(x) cout<<#x<<"="<<x<<endl
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const ll N=250009;
const ll mod=9875321; 
char name[N][12];
ll n,hs[9875329],score[N];
ll ch[N*2][2],tot,fa[2*N],size[N*2],v[N*2],id[N*2],rt,cnt[N];
ll lin[N*2],head[N],last[N],next[N],end[N],bt;// lins
//注意尽量不要和stl里面的东西重名,例如link,这里就要改为lin 
void up(ll i){size[i]=size[ch[i][0]]+size[ch[i][1]]+cnt[i];}
inline ll read()
{
	char ch;ll ans,f=1;
	while ((ch=getchar())<'0'||ch>'9') if (ch=='-') f=-1;ans=ch-'0';
	while ((ch=getchar())>='0'&&ch<='9') ans=ans*10+ch-'0';
	return ans*f;
}
void rot(ll x)
{
	ll y=fa[x],z=fa[y],l,r;
	if (ch[y][0]==x)l=0;else l=1;r=l^1;
	if (z)
	if (ch[z][0]==y) ch[z][0]=x;else ch[z][1]=x;
	fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
	ch[y][l]=ch[x][r];ch[x][r]=y;
	up(y);
}
void splay(ll x,ll k)
{
	ll y,z;
	while (fa[x]!=k)
	{
		y=fa[x],z=fa[y];
		if (z!=k)
		if (ch[z][0]==y^ch[y][0]==x) rot(x);else rot(y);
		rot(x);
	}
	if (k==0) rt=x;
	up(x);
}
void insert(ll val,ll b)
{
	if (rt==0)
	{
		rt=++tot;v[tot]=val;
		end[rt]=head[rt]=++bt;lin[bt]=b;
		cnt[tot]=1;up(tot);
		return;
	}
	ll i=rt,y;
	while (i)
	{
		size[i]++;
		if (v[i]==val)
		{
			cnt[i]++;
			lin[++bt]=b;next[head[i]]=bt;last[bt]=head[i];head[i]=bt;
			return;
		}
		y=ch[i][v[i]<val];
		if (!y)
		{
			v[++tot]=val;
			cnt[tot]=1;
			size[tot]=1;
			end[tot]=head[tot]=++bt;
			lin[bt]=b;
			fa[tot]=i;
			ch[i][v[i]<val]=tot;
			i=tot;
			break;
		}
		i=y;
	}
	splay(i,0);
}
ll find(ll i,ll val)
{
	if (i==0) return 0;
	if (v[i]==val) return i;
	if (v[i]>val) return find(ch[i][0],val);
	return find(ch[i][1],val);
}
void del(ll val,ll r)
{
	ll k=find(rt,val);
	for (int j=end[k];j;j=next[j])
	if (lin[j]==r)
	{
		next[last[j]]=next[j];
		last[next[j]]=last[j];
		if (head[k]==j) head[k]=last[j];
		if (end[k]==j) end[k]=next[j];
		break;
	}
	cnt[k]--;if (cnt[k]) return;
	splay(k,0);
	if (ch[k][0]==0&&ch[k][1]==0){rt=0;return;}
	if (ch[k][0]==0){rt=ch[k][1];fa[rt]=0;return;}
	if (ch[k][1]==0){rt=ch[k][0];fa[rt]=0;return;}
	ll y=ch[k][0];
	while (ch[y][1])y=ch[y][1];
	splay(y,k);
	fa[y]=0;fa[ch[k][1]]=y;rt=y;ch[y][1]=ch[k][1];
	up(y);
}
ll find_kth(ll i,ll k)
{
	if (i==0) return 0;
	if (size[ch[i][1]]>=k) return find_kth(ch[i][1],k);//调用函数时 
	if (size[ch[i][1]]+cnt[i]>=k) return i;
	return find_kth(ch[i][0],k-size[ch[i][1]]-cnt[i]);//	注意不要名字打错,调用错了!!!! 
}
void in(char *c,ll len)
{
	ll sco=read();
	ll k=0;
	for (int i=1;i<len;i++) k=((ll)k*29%mod+c[i]-'A'+1)%mod;
	if (hs[k]) 
	{
		del(score[hs[k]],hs[k]);
		score[hs[k]]=sco;
		insert(sco,hs[k]);
	}
	else 
	{
		score[++n]=sco;
		memcpy(name[n],c,len);
		hs[k]=n;
		insert(sco,n);
	}
}
void query_kth(char *c,ll len)
{
	ll k=0;
	for (int i=1;i<len;i++) k=k*10+c[i]-'0';
	ll h=find_kth(rt,k+1);splay(h,0);
	ll kk=0,g=0;
	for(int j=end[h];j;j=next[j])
	{
		g++;
		if (size[ch[h][1]]+g-1==k) break;
	}
	while (v[h]!=-inf)
	{
		for (int j=end[h];j;j=next[j])
		{
			g--;
			if (g>0) continue;
			kk++;
			printf("%s ",name[lin[j]]+1);
			if (kk==10) {printf("\n");return;}
		}
		h=ch[h][0];
		while (ch[h][1]) h=ch[h][1];
		splay(h,0);
	}
	printf("\n");
}
void query_rank(char *c,ll len)
{
	ll k=0;
	for (int i=1;i<len;i++) k=((ll)k*29%mod+c[i]-'A'+1)%mod;
	ll h=find(rt,score[hs[k]]);
	splay(h,0);
	ll ans=size[ch[h][1]];
	for (int j=end[h];j;j=next[j])
	{
		ans++;
		if (lin[j]==hs[k]) break; 
	}
	printf("%lld\n",ans-1);
}
int main()
{
	//freopen("rank.in","r",stdin);
	//freopen("rank.out","w",stdout);
	ll q=read();
	char c[15];
	insert(inf,1);
	insert(-inf,2);
	tot=2;
	while (q--)
	{
		scanf("%s",c);
		if (c[0]=='+') in(c,strlen(c));
		if (c[0]=='?')
		if (c[1]>='0'&&c[1]<='9') query_kth(c,strlen(c));
		else query_rank(c,strlen(c));
	}
	//fclose(stdin);
	//fclose(stdout);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值