2022.02.12 模拟赛
T3 rollcall
Step 1
这道题需要两个操作:
1.插入一个值;
2.求第k小的值。
很明显的平衡树,为了不用脑子,上来就是一个Treap。
Step 2
最开始想打FHQ Treap,后来一想,怎么存 \(same[x]\) ?于是放弃挣扎,直接来Treap。
代码如下:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<bits/stdc++.h>
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
#define R register
const int N=3e4+10;
int n,m,a[N];
struct node{
int num,id,ans;
}Q[N];
inline int cmp1(node x,node y){
return x.num<y.num;
}
inline int cmp2(node x,node y){
return x.id<y.id;
}
//struct FHQTreap{
int root,cnt,val[N],key[N],son[N][2],sizei[N],same[N],fa[N];
inline void update(int x){
sizei[x]=sizei[son[x][0]]+sizei[son[x][1]]+same[x];
}
inline void rotate(int &x,int flag){
int y=son[x][flag^1];
int change=son[y][flag];
son[x][flag^1]=change;
son[y][flag]=x;
update(x);
update(y);
x=y;
}
inline void insert(int &x,int vali){
if(!x){
x=++cnt;
sizei[x]=same[x]=1;
val[x]=vali;
key[x]=rand();
return ;
}
if(val[x]==vali)return (void)(++same[x],++sizei[x]);
int flag=vali>val[x];
insert(son[x][flag],vali);
if(key[x]<key[son[x][flag]])rotate(x,flag^1);
update(x);
}
inline int rank_score(int x,int k){
if(!x)return 0;
if(sizei[son[x][0]]>=k)return rank_score(son[x][0],k);
else if(sizei[son[x][0]]+same[x]>=k)return val[x];
else return rank_score(son[x][1],k-sizei[son[x][0]]-same[x]);
}
//}treap;
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')w=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0'){
s=s*10+ch-'0';
ch=getchar();
}
return s*w;
}
signed main(){
freopen("rollcall.in","r",stdin);
freopen("rollcall.out","w",stdout);
n=read();m=read();
for(R int i=1;i<=n;i++)a[i]=read();
for(R int i=1;i<=m;i++)Q[i].id=i,Q[i].num=read();
sort(Q+1,Q+m+1,cmp1);
int now=1;
for(R int i=1;i<=m;i++){
for(;now<=Q[i].num;now++)
insert(root,a[now]);//,cout<<a[now]<<" ";cout<<endl;
Q[i].ans=rank_score(root,Q[i].id);
//cout<<Q[i].ans<<endl;
}
sort(Q+1,Q+m+1,cmp2);
for(R int i=1;i<=m;i++)cout<<Q[i].ans<<endl;
return 0;
}
T2 car
Step 1
要求是个正方形,不用想,枚举对角线上的两个顶点,计算出其他点的位置,为了省事可以直接上map。
如果出现两个点在一个位置上—— map[make_pair(x,y)]=1 啊/斜眼笑
代码如下:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<bits/stdc++.h>
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
#define R register
const int N=1010;
int n;
struct node{
int x,y;
}car[N];
map<pair<int,int>,int>mapi;
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')w=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0'){
s=s*10+ch-'0';
ch=getchar();
}
return s*w;
}
signed main(){
freopen("car.in","r",stdin);
freopen("car.out","w",stdout);
n=read();
for(R int i=1;i<=n;i++){
car[i].x=read();car[i].y=read();
mapi[make_pair(car[i].x,car[i].y)]=1;
}
int ans=0;
for(R int i=1;i<=n;i++)
for(R int j=i+1;j<=n;j++){
int x=car[i].x,y=car[i].y,u=car[j].x,v=car[j].y;
int xi=abs(x-u),yi=abs(y-v);
//if(xi==0||yi==0)continue;
//if(mapi[make_pair(x,v)]==1&&mapi[make_pair(u,y)]==1)++ans,cout<<x<<" "<<y<<" "<<u<<" "<<v<<endl;
int x1=u-yi,y1=v+xi,x2=x-yi,y2=y+xi;
if(mapi[make_pair(x1,y1)]&&mapi[make_pair(x2,y2)])++ans;//,cout<<x<<" "<<y<<" "<<u<<" "<<v<<" "<<x1<<" "<<y1<<" "<<x2<<" "<<y2<<endl;
}
ans/=2;
cout<<ans;
return 0;
}
T1 disk
Step 1
简而言之就是有个可爱的栈和一个初始数组,可以进行两个操作:
1.把初始数组里的末尾数字扔进栈里;
2.把栈顶的数字弹出来。
每次可以进行一个操作,并且把被弹出来数字的顺序给了出来,问原来是数组里是否存在某些数字比它后面的数字小的情况。
Step 2
思索一下初始数组和出栈数组的关系:
如果初始数组单调递增,依次从尾至头扔入栈中,设第 \(i\) 个数 \(x\) 出栈,则栈内的数均大于 \(x\) ,并且从栈底到栈顶单调递减。
再思索一下栈内元素大小和出栈数组的关系:
如果栈内元素单调递增,那么出栈数组单调递减,设第 \(i\) 个数 \(x\) 出栈,则栈内元素均小于 \(x\) ,并且从栈底到栈顶单调递增。
所以需要判断每个数后面构成的序列是否递减,或者维护一个最大值,只需要判断比最大值小的序列是否递减,当更换最大值的时候序列清空。
代码如下:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<bits/stdc++.h>
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
#define R register
const int N=1e5+10;
int n,a[N],b[N],c[N];
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')w=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0'){
s=s*10+ch-'0';
ch=getchar();
}
return s*w;
}
signed main(){
freopen("disk.in","r",stdin);
freopen("disk.out","w",stdout);
while(~scanf("%d",&n)){
for(R int i=1;i<=n;i++)c[i]=a[i]=read();
sort(a+1,a+n+1);
int top1=1,top2=1,top3=0;
for(;top1<=n;top1++){
if(a[top1]==c[top2])++top2;
else if(a[top1]<c[top2])b[++top3]=top1;
else if(a[top1]>c[top2]){
for(;top3>=1;)
if(b[top3]==c[top2])--top3,++top2;
else break;
if(a[top1]!=c[top2])b[++top3]=a[top1];
else ++top2;
}
}
int ans=0;
while(top3){
if(b[top3]!=c[top2]){
ans=1;break;
}else --top3;
++top2;
}
if(ans)puts("J");
else puts("Y");
}
return 0;
}
posted on
浙公网安备 33010602011771号