n个套娃,套了几组,每秒能进行一次操作,简单地说是套只能套上单个,任意拆分,问全部套一起要多少秒。水题,就是题意坑。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int m[100010];
int cnt[100010];
int main(){
int n,k;
cin>>n>>k;
int ans=0;
int MAX=0;
for(int i=1;i<=k;i++){
scanf("%d",&m[i]);
int pre=0;
int num;
for(int j=1;j<=m[i];j++){
scanf("%d",&num);
if(num==pre+1){
cnt[i]++;
pre=num;
}
MAX=max(MAX,cnt[i]);
}
ans+=m[i]*2;
ans--;
}
ans-=MAX;
ans-=(MAX-1);
cout<<ans<<endl;
return 0;
}
n个不相交区间,m个已知长度的桥。要求为每两个相邻区间跨上一座桥。输出任意解,无解输出0。
贪心。每组相邻的区间,需要的桥的上下界是已知的,按上界升序排序,按顺序二分找最短的桥给它就行了。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=200010;
ll l[maxn];
ll r[maxn];
ll a[maxn];
int n,m;
int ans[maxn];
struct node{
ll MIN;
ll MAX;
int id;
bool operator<(const node other)const{
return MAX<other.MAX;
}
}seg[maxn];
struct Bridge{
ll len;
int id;
bool operator<(const Bridge other)const{
if(len!=other.len)return len<other.len;
return id<other.id;
}
};
int main(){
cin>>n>>m;
for(int i=0;i<n;i++){
scanf("%I64d%I64d",&l[i],&r[i]);
}
for(int i=0;i<n-1;i++){
seg[i].MIN=l[i+1]-r[i];
seg[i].MAX=r[i+1]-l[i];
seg[i].id=i;
}
set<Bridge> Set;
Bridge bb;
for(int i=0;i<m;i++){
scanf("%I64d",&bb.len);
bb.id=i;
Set.insert(bb);
}
sort(seg,seg+n-1);
bool ok=1;
for(int i=0;i<n-1;i++){
Bridge tmp; tmp.len=seg[i].MIN;
tmp.id=-1;
set<Bridge>::iterator it=Set.lower_bound(tmp);
if((*it).len>seg[i].MAX){
ok=0;
break;
}else{
ans[seg[i].id]=it->id;
Set.erase(*it);
}
}
if(ok){
cout<<"Yes"<<endl;
for(int i=0;i<n-1;i++){
printf("%d ",ans[i]+1);
}
}else{
cout<<"No"<<endl;
}
return 0;
}
一块n*n的网格状巧克力,吃掉了下三角,只剩上三角(x+y<=n+1)。有q次操作,每次指定斜线上(x+y=n+1)的一个格子,开始向上或向左吃,吃到不能再吃为止。对每次询问回答吃了多少个格子。
开始没注意看题,以为是二维线段树的神题,后来注意到开始吃的点位于斜线上。。。解题的关键是巧妙维护信息。把每次吃的格子的x坐标存到一个set里,对于每次询问,如果向上吃,就找x大的是哪一次,算y坐标的差;否则找x小的是哪一次,算x坐标的差。然后还要维护一下y或x,非常巧妙。。
#include <bits/stdc++.h>
using namespace std;
#define mp make_pair
#define pii pair<int,int>
const int maxn=200010;
int x[maxn];
int y[maxn];
int main(){
int n,q;
char dir[2];
cin>>n>>q;
set<pii> s; set<pii>::iterator it;
s.insert(mp(0,q+1)); x[q+1]=0; y[q+1]=n+1;
s.insert(mp(n+1,q+2)); x[q+2]=n+1; y[q+2]=0;
for(int i=1;i<=q;i++){
scanf("%d%d%s",&x[i],&y[i],dir);
if(dir[0]=='L'){ //找小的
it = s.upper_bound(mp(x[i]+1,0));
it--;
}else{ //找大的
it = s.lower_bound(mp(x[i],0));
}
if(it->first==x[i]){
printf("0\n");
continue;
}
s.insert(mp(x[i],i));
if(dir[0]=='L'){
printf("%d\n",x[i]-x[it->second]);
x[i]=x[it->second];
}else{
printf("%d\n",y[i]-y[it->second]);
y[i]=y[it->second];
}
}
return 0;
}
本文深入解析了三个复杂算法问题的解决策略,包括套娃问题、区间桥连接问题和巧克力网格问题。通过巧妙的算法设计,作者展示了如何在限制条件下找到最优解。文章详细解释了每种问题的思路、关键步骤和代码实现,旨在帮助读者理解和掌握复杂算法问题的求解方法。
1353

被折叠的 条评论
为什么被折叠?



