题面
样例
// input
6
0 0
1 0
1 1
3 1
5 1
7 1
//output
3
// input
8
5 1
5 0
5 0
2 1
3 0
4 0
100000000 1
1 0
//output
100000000
Round 1 90分
差不多像是前缀和问题,CSP的第二道大多数都是这个思路。
整体问题求解分成三个部分:遍历到第i个阈值为m,正确的数量 cnt=zeros[0:i)+ones(i:n-1]+is_one(i),后续需要处理一下重复部分。
写完才发现… 忽略了另外一个样例的情况… 【具有同值重复0和同值重复1的情况】(纯粹是没认真读题读样例了… 但感觉这个思路还是OK的…)
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1e5+5;
struct node{
int y,res,cnt=0;
}a[maxn];
int num[2][maxn];// 记录前i个
bool cmp(node p,node q)
{
if(p.y==q.y)
return p.res<q.res;
return p.y<q.y;
}
int main()
{
int n;
cin>>n;
memset(num,0,sizeof(num));
for(int i=0;i<n;i++)
{
cin>>a[i].y>>a[i].res;
}
sort(a,a+n,cmp);
// for(int i=0;i<n;i++)
// cout<<a[i].y<<" "<<a[i].res<<endl;
num[0][0]=0;
for(int i=1;i<n;i++)
{
if(a[i-1].res==0)
num[0][i]=num[0][i-1]+1;
else
num[0][i]=num[0][i-1];
}
num[1][n-1]=0;
for(int i=n-2;i>=0;i--) // 记录后i个为1的个数(不包括自己)
{
if(a[i+1].res==1)
num[1][i]=num[1][i+1]+1;
else
num[1][i]=num[1][i+1];
}
// for(int i=0;i<2;i++)
// {
// for(int j=0;j<n;j++)
// cout<<num[i][j]<<" ";
// cout<<endl;
// }
for(int i=0;i<n;i++)
{
if(a[i].y==a[i+1].y)
{
a[i+1].cnt-=1;//只处理了存在同值res=0/1的情况,见样例1
i+=1;
//cout<<a[i].y<<" "<<cnt<<endl;
}
if(a[i].res==1)
a[i].cnt+=num[0][i]+num[1][i]+1;
else
a[i].cnt+=num[0][i]+num[1][i];
//cout<<cnt<<endl;
}
int maxcnt=a[0].cnt;
int idx=0;
for(int i=1;i<n;i++)
{
//cout<<a[i].y<<" "<<a[i].cnt<<endl;
if(a[i].cnt>maxcnt)
{
maxcnt=a[i].cnt;
idx=a[i].y;
}
else if(a[i].cnt==maxcnt&&a[i].y>idx)
idx=a[i].y;
}
cout<<idx<<endl;
return 0;
}
简单的对输入去重是不可行的。
AC 100分
注意要去重,阈值遍历到该值时,如果res为1,则是应记录的。如果该值左边有重复0,应该减去相应的个数;如果res为0,右边重复1的情况同理。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1e5+5;
struct node{
int y,res,cnt=0;
}a[maxn];
int num[2][maxn];// 记录第i个数前面0的个数和后面1的个数
bool cmp(node p,node q)
{
if(p.y==q.y)
return p.res<q.res;
return p.y<q.y;
}
int main()
{
int n;
cin>>n;
memset(num,0,sizeof(num));
for(int i=0;i<n;i++)
{
cin>>a[i].y>>a[i].res;
}
sort(a,a+n,cmp);
// for(int i=0;i<n;i++)
// cout<<a[i].y<<" "<<a[i].res<<endl;
//开始记录前面0和后面1的个数
num[0][0]=0;
for(int i=1;i<n;i++)
{
if(a[i-1].res==0)
num[0][i]=num[0][i-1]+1;
else
num[0][i]=num[0][i-1];
}
num[1][n-1]=0;
for(int i=n-2;i>=0;i--) // 记录后i个为1的个数(不包括自己)
{
if(a[i+1].res==1)
num[1][i]=num[1][i+1]+1;
else
num[1][i]=num[1][i+1];
}
// for(int i=0;i<2;i++)
// {
// for(int j=0;j<n;j++)
// cout<<num[i][j]<<" ";
// cout<<endl;
// }
for(int i=0;i<n;i++)
{
//这种写法只考虑到了左边同值重复0的情况,没有考虑到右边重复1的情况
// if(a[i].y==a[i+1].y&&a[i].res==a[i+1].res)
// {
// if(a[i].res==0)
// a[i+1].cnt-=1;
// i+=1;
// //cout<<a[i].y<<" "<<cnt<<endl;
// }
// a[i+repeat].cnt-=repeat;
if(a[i].res==1)
{
a[i].cnt+=num[0][i]+num[1][i]+1;
int repeat=0;//同值情况 左边多出来0的个数
for(int k=i;k>=0;k--)
{
if(a[k].res==0)
repeat++;
if(a[k].y!=a[k-1].y)
break;
}
//cout<<a[i].y<<" repeat "<<repeat<<endl;
a[i].cnt-=repeat;
}
else
{
a[i].cnt+=num[0][i]+num[1][i];
int repeat=0;//同值情况 右边多出来1的个数
for(int k=i;k<n;k++)
{
if(a[k].res==1)
repeat++;
if(a[k].y!=a[k+1].y)
break;
}
//cout<<a[i].y<<" repeat "<<repeat<<endl;
a[i].cnt-=repeat;
}
}
// for(int i =0;i<n;i++)
// cout<<a[i].cnt<<" ";
// cout<<"****"<<endl;
int maxcnt=a[0].cnt;
int idx=0;
for(int i=1;i<n;i++)
{
//cout<<a[i].y<<" "<<a[i].cnt<<endl;
if(a[i].cnt>maxcnt)
{
maxcnt=a[i].cnt;
idx=a[i].y;
}
else if(a[i].cnt==maxcnt&&a[i].y>idx)
idx=a[i].y;
}
cout<<idx<<endl;
return 0;
}