题意: 找到一个最小的区间,使其能与所给的区间都有交点。
思路:
- 找到左端点的最大值L与端点的最小值R。
- 若L>R,则最小区间必须包含L与R;若L<=R,则最小区间可以小到为[L,R]中的任意一点。
刚开始没多想,就那么傻的直接把|L-R|当成了最小区间,呜呜~~
代码实现:
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+5;
#define inf 0x3f3f3f3f
int a[MAXN],b[MAXN];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int t; cin>>t;
while(t--)
{
int n,x=-1,y=inf; cin>>n;
for(int i=1;i<=n;i++) {
cin>>a[i]>>b[i];
x=max(x,a[i]);
y=min(y,b[i]);
}
if(n==1){
cout<<0<<endl;
continue;
}
if(x>y) cout<<x-y<<endl;
else cout<<0<<endl;
}
return 0;
}
题意: 题目给出n个元素的加密序列q,与n个元素的原序列p的关系为q[i]=max{p[1]…p[i]},要求你求出可能的原序列。
思路:
- 由于去q[i]=max{p[1]…p[i]},所以整个q序列一定是个递增趋势的序列,且相同的值一定会在一起。
- 那么只需要开一个数组vis[]标记q序列中元素的出现次数,对于出现次数为1的q[i]就等于p[i];而对于出现k次的元素q[i],则在[1,q[i]]内找到k个未出现的元素作为相应的p[]元素值。
- 若找不到则用一个变量标记一下,输出“-1”;若都能找到,最后输出相应的p序列即可。
注意题目所给的数据范围,在WA了好几次找了无数bug后总算写出来了,结果却超时:
代码实现:
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+5;
int q[MAXN],p[MAXN],vis[MAXN];
int t,n;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>t;
while(t--){
cin>>n;
int flag=0,tmp=0,cnt=0;
memset(vis,0,sizeof vis);
for(int i=1;i<=n;i++){
cin>>q[i];vis[q[i]]++;
if(vis[q[i]]==1) p[i]=q[i];
else if(vis[q[i]]>1){
tmp=1;
for(int j=q[i];j>0;j--){
if(!vis[j]){
p[i]=j;
vis[j]=1;
flag=1;
break;
}
}
if(!flag) cnt=1;
flag=0;
}
}
if(tmp&&cnt) cout<<-1<<endl;
else{
for(int i=1;i<=n;i++){
if(i==n) cout<<p[i]<<endl;
else cout<<p[i]<<" ";
}
}
}
return 0;
}
显然我没有考虑到输入n可以取到1e5,当输入1e5个100000时绝对会超时。因此,再又WA了好几遍后终于写出了正确代码~~
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+5;
int q[MAXN],p[MAXN],vis[MAXN];
int t,n;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>t;
while(t--){
cin>>n; int flag=0,cnt=0;
memset(vis,0,sizeof vis);
for(int i=1;i<=n;i++){cin>>q[i];vis[q[i]]++;}
for(int i=1;i<=n;i++)
{
if(vis[q[i]]==1) p[i]=q[i];
else if(vis[q[i]]>1)
{
p[i]=q[i];
int tmp=vis[q[i]];
for(int j=q[i];j>0;j--)
{
if(!vis[j]){
p[++i]=j;
flag=1;
vis[j]=1;
tmp--;
}
if(tmp==1) break;
}
if(!flag) cnt=1;
flag=0;
}
}
if(cnt)cout<<-1<<endl;
else
for(int i=1;i<=n;i++){
if(i==n) cout<<p[i]<<endl;
else cout<<p[i]<<" ";
}
}
return 0;
}
在用变量做标记处理时很容易会出错。。
D1. Optimal Subsequences (Easy Version)
题意: 要求你找出k个元素的子序列(序列和最大且字典序最小,序列的顺序为所给序列的顺序,即可以不相连但不能错位)中的第pos位数。
思路:
- 这个题相对不那么复杂,用结构体对所给序列进行降序排序(数值相同的则以其pos为处理值)。
- 再每次取前k个值对其进行升序排序(以pos为处理值),输出相应pos的数值即可。
代码实现:
#include<bits/stdc++.h>
using namespace std;
const int MAXN=110;
int n,m,k,pos;
struct node{
int id,da;
};
node a[MAXN],b[MAXN];
bool cmp1(node a,node b)
{
if(a.da>b.da) return 1;
else if(a.da==b.da){
if(a.id<b.id) return 1;
else return 0;
}
else return 0;
}
bool cmp2(node a,node b)
{
if(a.id<b.id) return 1;
else return 0;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i].da;
a[i].id=i;
}
sort(a+1,a+n+1,cmp1);
cin>>m;
while(m--){
cin>>k>>pos;
for(int i=1;i<=k;i++)
b[i]=a[i];
sort(b+1,b+k+1,cmp2);
cout<<b[pos].da<<endl;
}
return 0;
}