C:Mark and His Unfinished Essay
题目描述:
给定一个字符串,每次截取al-ar添加到a的后边,随后又q个询问,问第i个字符是什么?
主要思路:
将k递归到原字符上的位置,然后进行输出。
直接向后添加肯定会长度超限的,所以肯定是想办法递归到最初字符串的位置上。
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=2e5+10;
ll l[N],r[N],book[N];
int main()
{
int t;
cin>>t;
while(t--)
{
ll n,c,q;
cin>>n>>c>>q;
string s;
cin>>s;
l[0]=0;
r[0]=n;// 存储后一个的位置
for(int i=1;i<=c;i++)
{
ll ll,rr;
cin>>ll>>rr;
ll--;
rr--;
l[i]=r[i-1];
r[i]=l[i]+rr-ll+1;
// 标记当前位置是从之前的哪个位置复制过来的
book[i]=l[i]-ll;
}
while(q--)
{
ll k;
cin>>k;
k--;
// 依次向后推
for(int i=c;i;i--)
{
if(k<l[i]) continue;
else
k-=book[i];
}
cout<<s[k]<<endl;
}
}
return 0;
}
D:Mark and Lightbulbs
题目描述:
有n个灯泡,用n位的二进制串表示n个灯泡的开关情况。
给出灯泡现在的开关情况以及灯泡的目标情况。
问能否通过操作:
实现目标,最少需要操作多少次。
主要思路:
通过题目给出的操作条件可以看出来,(这里将连续相同的状态看作是一个块)对于一个块来说,只能改变块两边灯泡的开关状态,而不能改变块内部的状态,所以首先两个状态的块数应该相同。
注意,首尾没有办法改变!
标记每个块的位置信息,一个1块变化一个边界需要操作一次
标记全部01块的右边界(因为0块的右边界是1块的左边界)
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
vector<int> aa,bb;
typedef long long ll;
int main()
{
int t;
cin>>t;
while(t--)
{
aa.clear();
bb.clear();
int n;
cin>>n;
string s1,s2;
cin>>s1>>s2;
// 首尾没有办法改变,如果不同的话就-1
if(s1[0]!=s2[0]||s1[n-1]!=s2[n-1])
{
cout<<-1<<endl;
continue;
}
// 标记每个块的位置信息,一个1块变化一个边界需要操作一次
// 标记全部01块的右边界(因为0块的右边界是1块的左边界)
for(int i=0;i<n-1;i++)
{
if(s1[i]!=s1[i+1]) aa.push_back(i);
if(s2[i]!=s2[i+1]) bb.push_back(i);
}
if(aa.size()!=bb.size())
{
cout<<-1<<endl;
continue;
}
ll ans=0;
for(int i=0;i<aa.size();i++)
{
ans+=abs(aa[i]-bb[i]);
}
cout<<ans<<endl;
}
return 0;
}