先暴力一下试试水
直接写了两个冒泡提交,然后发现...
是的,只过了三成的案例
是不是因为冒泡太长时间了,先吃个饭回来继续。。。
上快排+比较器
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;
class MyComparator implements Comparator<Integer>
{
@Override
public int compare(Integer o1, Integer o2) {
// TODO Auto-generated method stub
return o2-o1;//降序
}
}
public class DoubleSort {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int m=sc.nextInt();
Integer[] a=new Integer[n];
for(int i=0;i<n;i++)
{
a[i]=i+1;
}
while(n>0)
{
int flag=sc.nextInt();
int i=sc.nextInt();
Comparator cp=new MyComparator();
if(flag==0)
{
Arrays.sort(a, 0, i, cp);
}
else
{
Arrays.sort(a,i-1,a.length);
}
n--;
}
for(int i=0;i<a.length;i++)
{
System.out.print(a[i]+" ");
}
}
}
commit...
只过了六成,还是没能全过...
这时候发现操作范围问题 有相当一部分的操作是无效的
范围大的覆盖范围小的,优化一下操作,提取有效操作
//建一个内部类记录连续出现的操作记录
public static class reco
{
int first;
int second;
reco(int a,int b)
{
first=a;//标记升降序
second=b;//标记边界
}
}
int n,m,top;
Scanner sc=new Scanner(System.in);
n=sc.nextInt();
m=sc.nextInt();
int[] arr=new int[n+1];
reco[] r=new reco[n+1];
top=0;
while(m!=0)
{
int p=sc.nextInt();
int q=sc.nextInt();
if(p==1&&top>0) {//升序
while(top>0&&r[top].first==1)
{//top记录上一个操作
if(r[top].second<=q) //找最左边界
q=r[top].second;
--top;
}
while(top>=2&&r[top-1].second>=q) {
top-=2;//删除一组操作(即0操作和1操作)
}
r[++top]=new reco(1,q);//top始终停留在要记录操作的前一步
}
if(p==0){//降序
while(top>0&&r[top].first==0) {
if(r[top].second>=q)//找最右边界
q=r[top].second;
--top;
}
while(top>=2&&r[top-1].second<=q)
top-=2;
r[++top]=new reco(0,q);
}
m--;
}
提取完成后到了关键一步,就是如何排序,继续用快排的话有点用牛刀了。
看了一下大佬们的思路(太妙了,要是考试我根本不会发现估计只会直接排序了吧)发现优化后的规律
第一个操作一定是0操作
0 1必然交替出现
由于只限制左右边界,发现每次操作完靠左右的数趋于固定,中间乱序,并逐渐向中间固定
int k=n;
int left=1;
int right=n;
for(int i=1;i<=top;i++) {//先后依次执行有效操作
if(r[i].first==0) {
while(left<=right&&r[i].second<right)//右边界范围内的升序操作
arr[right--]=k--;
}
if(r[i].first==1) {
while(left<=right&&r[i].second>left)//左边界范围内的降序操作
arr[left++]=k--;
}
}
//因为操作1必然是0操作,所以数字没被固定完时奇数降序偶数升序,直到全部固定完毕
if(top%2==0) {//升序
while(left<=right)
arr[right--]=k--;
}
else {//降序
while(left<=right)
arr[left++]=k--;
}
for(int i=1;i<=n;i++) {
System.out.print(arr[i]+" ");
}
赋上完整代码
import java.util.*;
public class DoubleSort2{
//无效步骤判断
//第一次一定是0操作
//当前操作范围囊括前面同类型的,前面步骤就可删去
//01交替依次往中间固定
//连续出现,范围覆盖
//建一个内部类记录连续出现的操作记录
public static class reco
{
int first;
int second;
reco(int a,int b)
{
first=a;//标记升降序
second=b;//标记边界
}
}
public static void main(String[] args)
{
int n,m,top;
Scanner sc=new Scanner(System.in);
n=sc.nextInt();
m=sc.nextInt();
int[] arr=new int[n+1];
reco[] r=new reco[n+1];
top=0;
while(m!=0)
{
int p=sc.nextInt();
int q=sc.nextInt();
if(p==1&&top>0) {//升序
while(top>0&&r[top].first==1)
{//top记录上一个操作
if(r[top].second<=q) //找最左边界
q=r[top].second;
--top;
}
while(top>=2&&r[top-1].second>=q) {
top-=2;//删除一组操作(即0操作和1操作)
}
r[++top]=new reco(1,q);//top始终停留在要记录操作的前一步
}
if(p==0){//降序
while(top>0&&r[top].first==0) {
if(r[top].second>=q)//找最右边界
q=r[top].second;
--top;
}
while(top>=2&&r[top-1].second<=q)
top-=2;
r[++top]=new reco(0,q);
}
m--;
}
int k=n;
int left=1;
int right=n;
for(int i=1;i<=top;i++) {//先后依次执行有效操作
if(r[i].first==0) {
while(left<=right&&r[i].second<right)//右边界范围内的升序操作
arr[right--]=k--;
}
if(r[i].first==1) {
while(left<=right&&r[i].second>left)//左边界范围内的降序操作
arr[left++]=k--;
}
}
//因为操作1必然是0操作,所以数字没被固定完时奇数降序偶数升序,直到全部固定完毕
if(top%2==0) {//升序
while(left<=right)
arr[right--]=k--;
}
else {//降序
while(left<=right)
arr[left++]=k--;
}
for(int i=1;i<=n;i++) {
System.out.print(arr[i]+" ");
}
}
}
提交一下看看
accepted