@zhangche0526
2017-04-17T04:31:37.000000Z
字数 12901
阅读 1508
讲义
样例输入
10 5 7
1 2 3 4 5 6 7 8 9 10
1 3 5 7 9
2 3 4 5 6 7 10
样例输出
YES
NO
YES
NO
YES
标准程序
#include<iostream>
#include<cstdio>
#define x node[x_p]
#define y node[y_p]
#define z node[z_p]
#define p node[p_p]
#define u node[u_p]
#define v node[v_p]
using namespace std;
const int MAXN=1000;
struct splayTree
{
//private
int root,size;
struct N
{
int lc,rc,fa;
int val;
N(){lc=rc=fa=val=0;}
}node[MAXN+1];int ncnt;
void lRotate(int x_p)
{
int y_p=x.rc;
x.rc=y.lc;
if(y.lc) node[y.lc].fa=x_p;
y.fa=x.fa;
if(!x.fa) root=y_p;
else if(x_p==node[x.fa].lc) node[x.fa].lc=y_p;
else node[x.fa].rc=y_p;
y.lc=x_p,x.fa=y_p;
}
void rRotate(int x_p)
{
int y_p=x.lc;
x.lc=y.rc;
if(y.rc) node[y.rc].fa=x_p;
y.fa=x.fa;
if(!x.fa) root=y_p;
else if(x_p==node[x.fa].lc) node[x.fa].lc=y_p;
else node[x.fa].rc=y_p;
y.rc=x_p,x.fa=y_p;
}
void splay(int x_p)
{
while(x.fa)
{
if(!node[x.fa].fa)
{
if(node[x.fa].lc==x_p) rRotate(x.fa);
else lRotate(x.fa);
}else if(node[x.fa].lc==x_p&&node[node[x.fa].fa].lc==x.fa)
{
rRotate(node[x.fa].fa);
rRotate(x.fa);
}else if(node[x.fa].rc==x_p&&node[node[x.fa].fa].rc==x.fa)
{
lRotate(node[x.fa].fa);
lRotate(x.fa);
}else if(node[x.fa].lc==x_p&&node[node[x.fa].fa].rc==x.fa)
{
rRotate(x.fa);
lRotate(x.fa);
}else
{
lRotate(x.fa);
rRotate(x.fa);
}
}
}
void replace(int u_p,int v_p)
{
if(!u.fa) root=v_p;
else if(u_p==node[u.fa].lc) node[u.fa].lc=v_p;
else node[u.fa].rc=v_p;
if(v_p) v.fa=u.fa;
}
int subtreeMin(int u_p)
{
while(u.lc) u_p=u.lc;
return u_p;
}
int subtreeMax(int u_p)
{
while(u.rc) u_p=u.rc;
return u_p;
}
//public
splayTree(){root=0,size=0,ncnt=0;}
void insert(int val)
{
int z_p=root;
int p_p=0;
while(z_p)
{
p_p=z_p;
if(node[z_p].val<val) z_p=node[z_p].rc;
else z_p=node[z_p].lc;
}
z_p=++ncnt;
z.val=val;
z.fa=p_p;
if(!p_p) root=z_p;
else if(p.val<z.val) p.rc=z_p;
else p.lc=z_p;
splay(z_p);
++size;
}
int find(int val)
{
int z_p=root;
while(z_p)
{
z=node[z_p];
if(z.val<val) z_p=z.rc;
else if(val<z.val) z_p=z.lc;
else return z_p;
}
return 0;
}
void erase(int val)
{
int z_p=find(val);
if(!z_p) return;
splay(z_p);
if(!z.lc) replace(z_p,z.rc);
else if(!z.rc) replace(z_p,z.lc);
else
{
int y_p=subtreeMin(z.rc);
if(y.fa!=z_p)
{
replace(y_p,y.rc);
y.rc=z.rc;
node[y.rc].fa=y_p;
}
replace(z_p,y_p);
y.lc=z.lc;
node[y.lc].fa=y_p;
}
--size;
}
int getMin() {return node[subtreeMin(root)].val;}
int getMax() {return node[subtreeMax(root)].val;}
bool isEmpty() {return root==0;}
int getSize() {return size;}
} spT;
int main()
{
int i;
int n,m,q;
scanf("%d%d%d",&n,&m,&q);
for(i=1;i<=n;i++)
{
int r;scanf("%d",&r);
spT.insert(r);
}
for(i=1;i<=m;i++)
{
int r;scanf("%d",&r);
spT.erase(r);
}
for(i=1;i<=m;i++)
{
int r;scanf("%d",&r);
if(spT.find(r)) printf("YES\n");
else printf("NO\n");
}
return 0;
}
时空限制
时间限制:10s
空间限制:162MB
题目背景
最近,阿Q开了一间宠物收养所。收养所提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物。每个领养者都希望领养到自己满意的宠物,阿Q根据领养者的要求通过他自己发明的一个特殊的公式,得出该领养者希望领养的宠物的特点值 a ( a 是一个正整数, a< ),而他也给每个处在收养所的宠物一个特点值。这样他就能够很方便的处理整个领养宠物的过程了,宠物收养所总是会有两种情况发生:被遗弃的宠物过多或者是想要收养宠物的人太多,而宠物太少。
一个领养者领养了一个特点值为 a 的宠物,而它本身希望领养的宠物的特点值为b,那么这个领养者的不满意程度为 abs(a-b) 。
任务描述
你得到了一年当中,领养者和被收养宠物到来收养所的情况,希望你计算所有收养了宠物的领养者的不满意程度的总和。这一年初始时,收养所里面既没有宠物,也没有领养者。
输入格式
第一行为一个正整数 n,n<=80000 ,表示一年当中来到收养所的宠物和领养者的总数。接下来的n行,按到来时间的先后顺序描述了一年当中来到收养所的宠物和领养者的情况。每行有两个正整数 a, b ,其中 a=0 表示宠物, a=1 表示领养者, b 表示宠物的特点值或是领养者希望领养宠物的特点值。(同一时间呆在收养所中的,要么全是宠物,要么全是领养者,这些宠物和领养者的个数不会超过 10000 个)
输出格式
仅有一个正整数,表示一年当中所有收养了宠物的领养者的不满意程度的总和 mod 1000000 以后的结果。
样例输入
5
0 2
0 4
1 3
1 2
1 5
样例输出
3
样例解释
abs(3-2) + abs(2-4)=3,最后一个领养者没有宠物可以领养
标准程序1 by张澈
#include<iostream>
#include<cstdio>
#define x node[x_p]
#define y node[y_p]
#define z node[z_p]
#define u node[u_p]
#define v node[v_p]
#define p node[p_p]
using namespace std;
const int MAXN=80000,INF=~0U>>1,P=1000000;
struct splayTree
{
int root,size;
int type;
struct N
{
int lc,rc,fa;
int val;
N(){lc=rc=fa=val=0;}
}node[MAXN+1];int ncnt;
void lRotate(int x_p)
{
int y_p=x.rc;
x.rc=y.lc;
if(y.lc) node[y.lc].fa=x_p;
y.fa=x.fa;
if(!x.fa) root=y_p;
else if(x_p==node[x.fa].lc) node[x.fa].lc=y_p;
else node[x.fa].rc=y_p;
y.lc=x_p,x.fa=y_p;
}
void rRotate(int x_p)
{
int y_p=x.lc;
x.lc=y.rc;
if(y.rc) node[y.rc].fa=x_p;
y.fa=x.fa;
if(!x.fa) root=y_p;
else if(x_p==node[x.fa].lc) node[x.fa].lc=y_p;
else node[x.fa].rc=y_p;
y.rc=x_p,x.fa=y_p;
}
void splay(int x_p)
{
while(x.fa)
{
if(!node[x.fa].fa)
{
if(node[x.fa].lc==x_p) rRotate(x.fa);
else lRotate(x.fa);
}else if(node[x.fa].lc==x_p&&node[node[x.fa].fa].lc==x.fa)
{
rRotate(node[x.fa].fa);
rRotate(x.fa);
}else if(node[x.fa].rc==x_p&&node[node[x.fa].fa].rc==x.fa)
{
lRotate(node[x.fa].fa);
lRotate(x.fa);
}else if(node[x.fa].lc==x_p&&node[node[x.fa].fa].rc==x.fa)
{
rRotate(x.fa);
lRotate(x.fa);
}else
{
lRotate(x.fa);
rRotate(x.fa);
}
}
}
void replace(int u_p,int v_p)
{
if(!u.fa) root=v_p;
else if(u_p==node[u.fa].lc) node[u.fa].lc=v_p;
else node[u.fa].rc=v_p;
if(v_p) v.fa=u.fa;
}
int subtreeMin(int u_p)
{
while(u.lc) u_p=u.lc;
return u_p;
}
splayTree(){root=size=ncnt=type=0;}
void insert(int val)
{
int z_p=root;
int p_p=0;
while(z_p)
{
p_p=z_p;
if(node[z_p].val<val) z_p=node[z_p].rc;
else z_p=node[z_p].lc;
}
z_p=++ncnt;
z.val=val;
z.fa=p_p;
if(!p_p) root=z_p;
else if(p.val<z.val) p.rc=z_p;
else p.lc=z_p;
splay(z_p);
++size;
}
void erase(int z_p)
{
splay(z_p);
if(!z.lc) replace(z_p,z.rc);
else if(!z.rc) replace(z_p,z.lc);
else
{
int y_p=subtreeMin(z.rc);
if(y.fa!=z_p)
{
replace(y_p,y.rc);
y.rc=z.rc;
node[y.rc].fa=y_p;
}
replace(z_p,y_p);
y.lc=z.lc;
node[y.lc].fa=y_p;
}
--size;
}
int work(int val,int rtype)
{
if(!size) {type=rtype;insert(val);return 0;}
if(rtype==type) {insert(val);return 0;}
int x_p=-1,y_p=-1,u_p=root;
while(u_p)
if(u.val<=val)
{
x_p=u_p;
u_p=u.rc;
}else u_p=u.lc;
u_p=root;
while(u_p)
if(u.val>=val)
{
y_p=u_p;
u_p=u.lc;
}else u_p=u.rc;
if(x_p==-1) x_p=y_p;
else if(y_p!=-1)
if(y.val-val<val-x.val) x_p=y_p;
erase(x_p);
return x.val>val?x.val-val:val-x.val;
}
} spT;
int main()
{
int i;int n;int ans=0;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
int rtype,val;
scanf("%d%d",&rtype,&val);
ans=(ans+spT.work(val,rtype))%P;
}
printf("%d\n",ans);
return 0;
}
标准程序2 by hzwer
#include<iostream>
#include<cstdio>
using namespace std;
const int MAXN=80000,P=1000000;
int n,size,root,t1,t2;
long long ans;
int ch[MAXN+1][2],num[MAXN+1],fa[MAXN+1];
void rotate(int x,int &k)
{
int y=fa[x],z=fa[y],l,r;
if(ch[y][0]==x) l=0;
else l=1;
r=l^1;
if(y==k) k=x;
else
{
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;
}
void splay(int x,int &k)
{
int y,z;
while(x!=k)
{
y=fa[x],z=fa[y];
if(y!=k)
{
if((ch[y][0]==x)^(ch[z][0]==y))
rotate(x,k);
else rotate(y,k);
}
rotate(x,k);
}
}
void insert(int &k,int x,int last)
{
if(k==0){size++;k=size;num[k]=x;fa[k]=last;splay(k,root);return;}
if(x<num[k]) insert(ch[k][0],x,k);
else insert(ch[k][1],x,k);
}
void del(int x)
{
splay(x,root);
if(ch[x][0]*ch[x][1]==0)
root=ch[x][0]+ch[x][1];
else
{
int k=ch[x][1];
while(ch[k][0]) k=ch[k][0];
ch[k][0]=ch[x][0];fa[ch[x][0]]=k;
root=ch[x][1];
}
fa[root]=0;
}
void ask_before(int k,int x)
{
if(k==0) return;
if(num[k]<=x)
{
t1=k;
ask_before(ch[k][1],x);
}
else ask_before(ch[k][0],x);
}
void ask_after(int k,int x)
{
if(k==0) return;
if(num[k]>=x)
{
t2=k;
ask_after(ch[k][0],x);
}
else ask_after(ch[k][1],x);
}
int main()
{
scanf("%d",&n);
int rtype,atype,x;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&rtype,&x);
if(!root)
{
atype=rtype;
insert(root,x,0);
}
else if(rtype==atype) insert(root,x,0);
else
{
t1=t2=-1;
ask_before(root,x);ask_after(root,x);
if(t1==-1)
{
ans+=num[t2]-x;
ans%=P;del(t2);
}
else if(t2==-1)
{
ans+=x-num[t1];
ans%=P;del(t1);
}
else
{
if(x-num[t1]>num[t2]-x)
{
ans+=num[t2]-x;
ans%=P;del(t2);
}
else
{
ans+=x-num[t1];
ans%=P;del(t1);
}
}
}
}
cout<<ans<<endl;
return 0;
}
题目描述
Tiger 最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。Tiger 拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况: 该天的最小波动值。
当最小波动值越大时,就说明营业情况越不稳定。
而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助 Tiger 来计算这一个值。 第一天的最小波动值为第一天的营业额。
输入格式
第一行为正整数,表示该公司从成立一直到现在的天数,接下来的n行每行有一个整数(有可能有负数),表示第i天公司的营业额。
天数n<=32767,每天的营业额ai <= 1,000,000。
最后结果
输出格式
输出文件仅有一个正整数,即 Sigma (每天最小的波动值)。结果小于 。
样例输入
6
5
1
2
5
4
6
样例输入
12
样例解释
这道题纯属是给大家练手的,因为此题与例题相似而且还要简单,因为对这道题不必想如何统计前面树中的最小值,因为此题是要每个数都要插入的,插入完之后此节点一定是根节点,那么只要取右子树中的最小值和左子树中的最大值与此节点的差值即可。最难的删除操作在此题也不涉及。
唯一的不同点就是这道题的数据不保证没有重复,所以插入的时候如果发现此数值已经在树中就不必插入了。
标准程序 by 张澈
#include<iostream>
#include<cstdio>
#define x node[x_p]
#define y node[y_p]
#define z node[z_p]
#define p node[p_p]
#define u node[u_p]
#define v node[v_p]
#define min(a,b) (a<b?a:b)
using namespace std;
const int MAXN=32767,INF=~0U>>1;
struct splayTree
{
int root,size;
struct N
{
int lc,rc,fa;
int val;
N(){lc=rc=fa=val=0;}
}node[MAXN+10];int ncnt;
void lRotate(int x_p)
{
int y_p=x.rc;
x.rc=y.lc;
if(y.lc) node[y.lc].fa=x_p;
y.fa=x.fa;
if(!x.fa) root=y_p;
else if(x_p==node[x.fa].lc) node[x.fa].lc=y_p;
else node[x.fa].rc=y_p;
y.lc=x_p,x.fa=y_p;
}
void rRotate(int x_p)
{
int y_p=x.lc;
x.lc=y.rc;
if(y.rc) node[y.rc].fa=x_p;
y.fa=x.fa;
if(!x.fa) root=y_p;
else if(x_p==node[x.fa].lc) node[x.fa].lc=y_p;
else node[x.fa].rc=y_p;
y.rc=x_p,x.fa=y_p;
}
void splay(int x_p)
{
while(x.fa)
{
if(!node[x.fa].fa)
{
if(node[x.fa].lc==x_p) rRotate(x.fa);
else lRotate(x.fa);
}else if(node[x.fa].lc==x_p&&node[node[x.fa].fa].lc==x.fa)
{
rRotate(node[x.fa].fa);
rRotate(x.fa);
}else if(node[x.fa].rc==x_p&&node[node[x.fa].fa].rc==x.fa)
{
lRotate(node[x.fa].fa);
lRotate(x.fa);
}else if(node[x.fa].lc==x_p&&node[node[x.fa].fa].rc==x.fa)
{
rRotate(x.fa);
lRotate(x.fa);
}else
{
lRotate(x.fa);
rRotate(x.fa);
}
}
}
int subtreeMin(int u_p)
{
while(u.lc) u_p=u.lc;
return u_p;
}
int subtreeMax(int u_p)
{
while(u.rc) u_p=u.rc;
return u_p;
}
splayTree(){root=0,size=0,ncnt=0;}
int insert(int val)
{
int z_p=root;
int p_p=0;
while(z_p)
{
p_p=z_p;
if(z.val==val) return 1;
if(z.val<val) z_p=node[z_p].rc;
else z_p=node[z_p].lc;
}
z_p=++ncnt;
z.val=val;
z.fa=p_p;
if(!p_p) root=z_p;
else if(p.val<z.val) p.rc=z_p;
else p.lc=z_p;
splay(z_p);
++size;
return 0;
}
int work(int val)
{
if(insert(val)) return 0;
if(size==1) return val;
int tmp=subtreeMin(node[root].rc);
if(!node[root].lc)
return node[subtreeMin(node[root].rc)].val-val;
if(!node[root].rc)
return val-node[subtreeMax(node[root].lc)].val;
return min(node[subtreeMin(node[root].rc)].val-val,
val-node[subtreeMax(node[root].lc)].val);
}
} spT;
int main()
{
int i;
int n;
int ans=0;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
int rn;scanf("%d",&rn);
ans+=spT.work(rn);
}
printf("%d\n",ans);
return 0;
}
题目描述
有 n 个人,每个人有两个属性 x 和 y 。如果对于一个人 ,不存在另外一个人 ,使得 ,或者 ,我们说 P 是有有事的。每次给出一个人的信息,要求输出在只考虑当前一伙的的信息的前提下,多少人是有优势的。
输入格式
输入第一行位测试数据组数 T 。每组数据第一行为整数 n (0<=n<=15000) ,以下 n 行每行两个整数 x,y ,分别为每个人的两个属性(不超过 的非负整数)。
输出格式
对于每组数据,输出获得每条信息后,有优势的人数。
这道题依旧不难,主要思路为:
对于每个人,判断其有没有优势(可通过判断小于他的最大的那个人的 y 坐标是否大于他的 y 坐标)。若没有优势就完事了;若有优势,加入平衡树,并删除所有因其加入而变得没有优势的人(即为横纵坐标都大于他的人)。
有两点需要注意:
本题我还没调完
#include<iostream>
#include<cstdio>
#define x node[x_p]
#define y node[y_p]
#define z node[z_p]
#define p node[p_p]
#define u node[u_p]
#define v node[v_p]
using namespace std;
const int MAXN=1000;
struct P
{
int a,b;
bool operator < (const P & ot) const
{return a<ot.a||(a==ot.a&&b<ot.b);}
};
struct splayTree
{
int root,size;
struct N
{
int lc,rc,fa;
P val;
int num;
N(){lc=rc=fa=num=0;}
}node[MAXN+1];int ncnt;
void lRotate(int x_p)
{
int y_p=x.rc;
x.rc=y.lc;
if(y.lc) node[y.lc].fa=x_p;
y.fa=x.fa;
if(!x.fa) root=y_p;
else if(x_p==node[x.fa].lc) node[x.fa].lc=y_p;
else node[x.fa].rc=y_p;
y.lc=x_p,x.fa=y_p;
}
void rRotate(int x_p)
{
int y_p=x.lc;
x.lc=y.rc;
if(y.rc) node[y.rc].fa=x_p;
y.fa=x.fa;
if(!x.fa) root=y_p;
else if(x_p==node[x.fa].lc) node[x.fa].lc=y_p;
else node[x.fa].rc=y_p;
y.rc=x_p,x.fa=y_p;
}
void splay(int x_p)
{
while(x.fa)
{
if(!node[x.fa].fa)
{
if(node[x.fa].lc==x_p) rRotate(x.fa);
else lRotate(x.fa);
}else if(node[x.fa].lc==x_p&&node[node[x.fa].fa].lc==x.fa)
{
rRotate(node[x.fa].fa);
rRotate(x.fa);
}else if(node[x.fa].rc==x_p&&node[node[x.fa].fa].rc==x.fa)
{
lRotate(node[x.fa].fa);
lRotate(x.fa);
}else if(node[x.fa].lc==x_p&&node[node[x.fa].fa].rc==x.fa)
{
rRotate(x.fa);
lRotate(x.fa);
}else
{
lRotate(x.fa);
rRotate(x.fa);
}
}
}
void replace(int u_p,int v_p)
{
if(!u.fa) root=v_p;
else if(u_p==node[u.fa].lc) node[u.fa].lc=v_p;
else node[u.fa].rc=v_p;
if(v_p) v.fa=u.fa;
}
splayTree(){root=0,size=0,ncnt=0;}
void insert(P val)
{
int z_p=root;
int p_p=0;
while(z_p)
{
p_p=z_p;
if(z.val==val) {++z.num;return;}
if(z.val<val) z_p=z.rc;
else z_p=z.lc;
}
z_p=++ncnt;
z.val=val;z.fa=p_p;z.num=1;
if(!p_p) root=z_p;
else if(p.val<z.val) p.rc=z_p;
else p.lc=z_p;
splay(z_p);
++size;
}
void erase(int z_p)
{
if(!z_p) return;
if(z.num>1) {--z.num;return;}
splay(z_p);
if(!z.lc) replace(z_p,z.rc);
else if(!z.rc) replace(z_p,z.lc);
else
{
int y_p=subtreeMin(z.rc);
if(y.fa!=z_p)
{
replace(y_p,y.rc);
y.rc=z.rc;
node[y.rc].fa=y_p;
}
replace(z_p,y_p);
y.lc=z.lc;
node[y.lc].fa=y_p;
}
--size;
}
int lower(P val)
{
int x_p=0,u_p=root;
while(u_p)
if(u.val<=val)
{
x_p=u_p;
u_p=u.rc;
}else u_p=u.lc;
return u_p;
}
int upper(P val)
{
int x_p=0,u_p=root;
while(u_p)
if(u.val>=val)
{
x_p=u_p;
u_p=u.lc;
}else u_p=u.rc;
return u_p;
}
void work(P val)
{
int x_p=lower(val);
if(x.val.b<val.b) return;
insert(val);
int y_p=upper(val);
while(y.val.b>val.b)
{
erase(y_p);
val=y.val;
y_p=upper(val);
}
}
int getSize() {return size;}
} spT;
int main()
{
freopen("xt.in","r",stdin);
freopen("xt.out","w",stdout);
int T,cNum;
scanf("%d",&T);
for(cNum=1;cNum<=T;cNum++)
{
if(cNum>1) printf("\n");
printf("Case #%d:\n",cNum);
int n;scanf("%d",&n);
spT=splayTree();
while(n--)
{
int a,b;scanf("%d%d",&a,&b);
P val=(P){a,b};
spT.work(val);
printf("%d\n",spT.getSize());
}
}
}