题目名称 |
盘子序列 |
四轮车 |
点名 |
提交文件 |
disk.pas/c/cpp |
car.pas/c/cpp |
rollcall.pas/c/cpp |
输入文件 |
disk.in |
car.in |
rollcall.in |
输出文件 |
disk.out |
car.out |
rollcall.out |
时间限制 |
1s |
1s |
1s |
空间限制 |
128M |
128M |
128M |
评测方式 |
传统 |
传统 |
传统 |
盘子序列
【题目描述】
有 n 个盘子。盘子被生产出来后,被按照某种顺序摞在一起。初始盘堆中如果一
个盘子比所有它上面的盘子都大,那么它是安全的,否则它是危险的。称初始盘堆为
A,另外有一个开始为空的盘堆 B。为了掩盖失误,生产商会对盘子序列做一些“处
理”,每次进行以下操作中的一个:(1)将 A 最上面的盘子放到 B 最上面;(2)将 B 最上
面的盘子给你。在得到所有 n 个盘子之后,你需要判断初始盘堆里是否有危险的盘子。
【输入格式】
输入文件包含多组数据(不超过 10 组)
每组数据的第一行为一个整数 n
接下来 n 个整数,第 i 个整数表示你收到的第 i 个盘子的大小
【输出格式】
对于每组数据,如果存在危险的盘子,输出”J”,否则输出”Y”
【样例输入】
3
2 1 3
3
3 1 2
【样例输出】
Y
J
【数据范围】
20%的数据保证 n<=8
80%的数据保证 n<=1,000
100%的数据保证 1<=n<=100,000,0<盘子大小<1,000,000,000 且互不相等
/* 读懂题目就好了 栈模拟一下 开始打错文件了!! */ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 1000010 using namespace std; int n,a[maxn],b[maxn],c[maxn],falg,top; int main() { freopen("disk.in","r",stdin); freopen("disk.out","w",stdout); while(scanf("%d",&n)!=EOF){ falg=top=0; for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) c[i]=a[i]; sort(a+1,a+1+n); int p1,p2=1; for(p1=1;p1<=n;p1++){ if(a[p1]==c[p2]){ p2++;continue; } if(a[p1]<c[p2])b[++top]=p1; else{ for(;top>0;){ if(b[top]==c[p2]){ top--;p2++; } else break; } if(a[p1]!=c[p2])b[++top]=a[p1]; else p2++; } } while(top){ if(b[top]!=c[p2]){ falg=1;break; } else top--;p2++; } if(falg)printf("J "); else printf("Y "); } return 0; }
四轮车
【题目描述】
在地图上散落着 n 个车轮,小 J 想用它们造一辆车。要求如下:
- 一辆车需要四个车轮,且四个车轮构成一个正方形
- 车轮不能移动你需要计算有多少种造车的方案(两个方案不同当且仅当所用车轮不全相同,坐
标相同的两个车轮视为不同车轮)。
【输入格式】
第一行一个整数 n
接下来 n 行,每行两个整数 x y,表示在(x,y)处有一个车轮
【输出格式】
一行一个整数,表示方案数
【样例输入】
9
0 0
1 0
2 0
0 2
1 2
2 2
0 1
1 1
2 1
【样例输出】
6
【数据范围】
30%的数据保证 n ≤ 30
100%的数据保证 1 ≤ n ≤ 1000; |x|, |y| < 20000
/* 枚举对角线上的点 算出剩下的两个 然后看有没有 没有用hash 直接二分找 也挺快的 */ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 10010 using namespace std; int n,ans[maxn],x1,x2,x3,x4,y1,y2,y3,y4,xx[maxn],yy[maxn],p1,p2; struct node{ int x,y; }P[maxn]; int cmp(const node &a,const node &b){ return a.x<b.x; } int Abs(int a){ return a<0?-a:a; } void Add(){ ans[1]++; for(int i=1;i<=ans[0];i++) if(ans[i]>9){ ans[i]%=10; ans[i+1]++; } if(ans[ans[0]+1])ans[0]++; } void Cal(int i,int j){ x1=xx[i];y1=yy[i];x2=xx[j];y2=yy[j]; int a=Abs(y1-y2),b=Abs(x1-x2); int c=Abs(a-b); if(c%2)x3=x4=y3=y4=0; else{ c>>=1; if(a<b){ x3=x1+c;y3=y2+c; x4=x2-c;y4=y1-c; } else{ x3=x1-c;y3=y2-c; x4=x2+c;y4=y1+c; } } } bool Judge(){ if(!x3&&!x4&&!y3&&!y4)return 0; int falg=0,flag=0; p1=lower_bound(xx+1,xx+1+n,x3)-xx; p2=upper_bound(xx+1,xx+1+n,x3)-xx; for(int i=p1;i<p2;i++){ if(xx[i]!=x3)return 0; if(yy[i]==y3){ falg=1;break; } } p1=lower_bound(xx+1,xx+1+n,x4)-xx; p2=upper_bound(xx+1,xx+1+n,x4)-xx; for(int i=p1;i<p2;i++){ if(xx[i]!=x4)return 0; if(yy[i]==y4){ flag=1;break; } } return falg&&flag; } int main() { freopen("car.in","r",stdin); freopen("car.out","w",stdout); scanf("%d",&n);ans[0]=1; for(int i=1;i<=n;i++) scanf("%d%d",&P[i].x,&P[i].y); sort(P+1,P+1+n,cmp); for(int i=1;i<=n;i++){ xx[i]=P[i].x; yy[i]=P[i].y; } for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++){ if(yy[i]>=yy[j])continue; Cal(i,j); if(Judge())Add(); } for(int i=ans[0];i>=1;i--) printf("%d",ans[i]); return 0; }
点名
【题目描述】
在 J 班的体育课上,同学们常常会迟到几分钟,但体育老师的点名却一直很准时。
老师只关心同学的身高,他会依次询问当前最高的身高,次高的身高,第三高的身高,
等等。在询问的过程中,会不时地有人插进队伍里。你需要回答老师每次的询问。
【输入格式】
第一行两个整数 n m,表示先后有 n 个人进队,老师询问了 m 次
第二行 n 个整数,第 i 个数 Ai 表示第 i 个进入队伍的同学的身高为 Ai
第三行 m 个整数,第 j 个数 Bj 表示老师在第 Bj 个同学进入队伍后有一次询问
【输出格式】
m 行,每行一个整数,依次表示老师每次询问的答案。数据保证合法
【样例输入】
7 4
9 7 2 8 14 1 8
1 2 6 6
【样例输出】
9
9
7
8
【样例解释】
(9){No.1 = 9}; (9 7){No.2 = 9}; (9 7 2 8 14 1){No.3 = 7; No.4 = 8}
【数据范围】
40%的数据保证 n ≤ 1000
100%的数据保证 1 ≤ m ≤ n ≤ 30000; 0 ≤ Ai < 232
暴力set 70分
:
#include<iostream> #include<cstdio> #include<cstring> #include<set> #define maxn 30010 using namespace std; long long n,m,x,c[maxn],a[maxn],cnt; multiset<long long>s; multiset<long long>::iterator p; int main() { freopen("rollcall.in","r",stdin); freopen("rollcall.out","w",stdout); cin>>n>>m; for(long long i=1;i<=n;i++) cin>>a[i]; for(long long i=1;i<=m;i++){ cin>>x;c[x]++; } s.clear(); for(long long i=1;i<=n;i++){ s.insert(a[i]); while(c[i]){ c[i]--; p=s.begin(); for(long long j=1;j<=cnt;j++)p++; cout<<*p<<endl;cnt++; } } return 0; }
主席树:
/*正解好像是搞了两个堆 没仔细看*/ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define ll long long #define maxn 30010 #define maxm 1000010 using namespace std; ll n,m,cnt,num,a[maxn],root[maxn],order[maxn]; struct node{ ll lc,rc,sum; }t[maxm*5]; ll init(){ ll x=0,f=1;char s=getchar(); while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} return x*f; } ll Build(ll S,ll L,ll R){ ll k=++cnt;t[k].sum=S; t[k].lc=L;t[k].rc=R; return k; } void Insert(ll &root,ll pre,ll pos,ll l,ll r){ root=Build(t[pre].sum+1,t[pre].lc,t[pre].rc); if(l==r)return; ll mid=l+r>>1; if(pos<=mid)Insert(t[root].lc,t[pre].lc,pos,l,mid); else Insert(t[root].rc,t[pre].rc,pos,mid+1,r); } ll Query(ll L,ll R,ll pos,ll l,ll r){ if(l==r)return l; ll sum=t[t[R].lc].sum-t[t[L].lc].sum; ll mid=l+r>>1; if(sum>=pos)return Query(t[L].lc,t[R].lc,pos,l,mid); else return Query(t[L].rc,t[R].rc,pos-sum,mid+1,r); } int main() { freopen("rollcall.in","r",stdin); freopen("rollcall.out","w",stdout); n=init();m=init(); for(ll i=1;i<=n;i++){ a[i]=init(); order[i]=a[i]; } sort(order+1,order+1+n); num=unique(order+1,order+1+n)-order-1; for(ll i=1;i<=n;i++){ ll pos=lower_bound(order+1,order+1+num,a[i])-order; Insert(root[i],root[i-1],pos,1,num); } ll l,r,k; for(ll i=1;i<=m;i++){ l=1;r=init();k=i; ll p=Query(root[l-1],root[r],k,1,num); cout<<order[p]<<endl; } return 0; }