这场作者挺钟爱双指针呀!
A、Shortest Path with Obstacle
大意
给你三个点a,b,f,输出a点到b点不经过f点的最短距离。
思路
当a,b,f点共线且f点在a、b点中间的情况时需要加2,其他情况直接求即可。
CODE
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod=1e9+7;
#define maxn 10000000
int t;
int main()
{
ios::sync_with_stdio(0);
cin>>t;
while(t--)
{
int x1,x2,x3,y1,y2,y3;
cin>>x1>>y1;
cin>>x2>>y2;
cin>>x3>>y3;
ll ans=0;
if((x1==x2&&x2==x3))
{
if(y3>max(y1,y2)||y3<min(y1,y2))
ans=abs(y1-y2);
else
ans=abs(y1-y2)+2;
}
else if(y1==y2&&y2==y3)
{
if(x3>max(x1,x2)||x3<min(x1,x2))
ans=abs(x1-x2);
else
ans=abs(x1-x2)+2;
}
else
{
ans=abs(x1-x2)+abs(y1-y2);
}
cout<<ans<<endl;
}
return 0;
}
B、Alphabetical Strings
大意
给定一个字符串,当字符串是由次字符串”a“开始,之后在次字符串左边或右边按字母序依次添加字母形成的时,输出"YES",否则,输出“NO”.
思路
遍历找到字母‘a’,不存在则直接输出“NO”,否则,建立一个双指针指向字母‘a’左右两侧,按字母序依次向左右两侧扩张,如双指针成功到达两边边界则输出“YES”,否则,输出“NO”.
CODE
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod=1e9+7;
#define maxn 10000000
int t;
int main()
{
ios::sync_with_stdio(0);
cin>>t;
while(t--)
{
string s;
cin>>s;
int si=s.size();
int num=-1;
for(int i=0;i<si;i++)
{
if(s[i]=='a')
{
num=i;
}
}
if(num==-1)
{
cout<<"NO"<<endl;
continue;
}
int x=num-1,y=num+1;
for(int i=1;i<si;i++)
{
if(x>=0)
{
if(s[x]=='a'+i)
{
x--;
continue;
}
}
if(y<si)
{
if(s[y]=='a'+i)
{
y++;
continue;
}
}
break;
}
if(x==-1&&y==si)
{
cout<<"YES"<<endl;
}
else
{
cout<<"NO"<<endl;
}
}
return 0;
}
C、Pair Programming
大意
两个人往一个公共序列中依次输出自己序列的数,给定初始页数,两个人在公共序列中输出的数为0时则页数+1,否则输出的数必须小于当前页数才是合法的,询问是否存在这样一个公共序列并输出它。
思路
屌英语难读的一批,重构了两次,这屌题卡我半小时,头疼。。。orz
贪心思路,双指针指向两人各自序列第一个数,为0就输出0,否则比较两个数谁小一点输出谁。
CODE
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod=1e9+7;
#define maxn 10000000
int t;
int a[107],b[107],c[307];
int main()
{
ios::sync_with_stdio(0);
cin>>t;
while(t--)
{
int k,n,m;
cin>>k>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<=m;i++)
{
cin>>b[i];
}
a[n+1]=INT_MAX;
b[m+1]=INT_MAX;
int x=1,y=1,num=0,flag=0;
for(int i=1;i<=n+m;i++)
{
if(a[x]==0)
{
c[++num]=a[x];
k++;
x++;
}
else if(b[y]==0)
{
c[++num]=b[y];
k++;
y++;
}
else if(a[x]<=b[y])
{
if(a[x]<=k)
{
c[++num]=a[x];
x++;
}
else
{
flag=1;
break;
}
}
else
{
if(b[y]<=k)
{
c[++num]=b[y];
y++;
}
else
{
flag=1;
break;
}
}
}
if(flag)
{
cout<<-1<<endl;
}
else
{
for(int i=1;i<=num;i++)
{
if(i==1)
cout<<c[i];
else
cout<<' '<<c[i];
}
cout<<endl;
}
}
return 0;
}
D、Co-growing Sequence
大意
定义一个序列a[i]&a[i+1]=a[i],则叫这个序列增长序列,即a[i]二进制位上为1则a[i+1]对应位上也必须为1.
现给定一个序列a,求字典序最小的序列b,使得a[i]^b[i]后得到的新的序列是增长序列。
思路
求字典序最小的b[i]即a[i-1]中二进制位为1且a[i]对应二进制位不为1时可通过异或补全,所以我们可用lowbit遍历a[i-1]每一个二进制位为1的数,把所有和a[i]与运算为0的数相加之和输出即为字典序最小b[i].
CODE
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod=1e9+7;
#define maxn 10000000
ll t;
ll a[200007];
ll lowbit(ll x)
{
return x&-x;
}
int main()
{
ios::sync_with_stdio(0);
cin>>t;
while(t--)
{
ll n;
cin>>n;
for(ll i=1;i<=n;i++)
{
cin>>a[i];
}
cout<<'0';
for(ll i=2;i<=n;i++)
{
ll ans=0;
while(a[i-1])
{
ll tmp=lowbit(a[i-1]);
a[i-1]-=tmp;
if(tmp&a[i])
{
continue;
}
else
{
a[i]+=tmp;
ans+=tmp;
}
}
cout<<' '<<ans;
}
cout<<endl;
}
return 0;
}
E、Air Conditioners
大意
给定n个格子,存在k个空调分布在这n个格子中,每个格子最多一个空调,每个格子的温度为遍历每个空调位置与该格子距离之差的绝对值加空调温度的最小值。
输出每个格子的温度
思路
每个格子只会受到左边或右边空调的影响,那么我们只需要处理两次来自右边和来自左边的空调
,并存储影响最大的空调导致的该格子温度,最后输出这一格来自左边的温度和来自右边的温度的最小值即可。
时间到了,bug没改完呜呜呜!
CODE
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod=1e9+7;
#define maxn 10000000
int t;
struct node
{
int x,y;
}a[300007];
bool cmp(node &f,node &s)
{
return f.x<s.x;
}
int le[300007],ri[300007];
int main()
{
ios::sync_with_stdio(0);
cin>>t;
while(t--)
{
int n,k;
cin>>n>>k;
for(int i=1;i<=k;i++)
{
cin>>a[i].x;
}
for(int i=1;i<=k;i++)
{
cin>>a[i].y;
}
sort(a+1,a+k+1,cmp);
int ans=a[1].x+a[1].y,num=1;
for(int i=1;i<=n;i++)
{
ans++;
if(i==a[num].x)
{
ans=min(ans,a[num].y);
if(num<k)
{
num++;
}
}
le[i]=ans;
}
ans=a[k].y-a[k].x+n+1,num=k;
for(int i=n;i>=1;i--)
{
ans++;
if(i==a[num].x)
{
ans=min(ans,a[num].y);
if(num>1)
num--;
}
ri[i]=ans;
}
for(int i=1;i<=n;i++)
{
if(i==1)
cout<<min(le[i],ri[i]);
else
cout<<" "<<min(le[i],ri[i]);
}
cout<<endl;
}
return 0;
}