题目
作为一个ACM菜鸟的我。。昨晚刚看这道题的时候,咋一看上去,不就是水题一道嘛。。。后面在wa了多次,无意见看到某大牛的博客才看到。。 用通常的方法来吧所需要的那个字符串给存起来,那是绝对做不到的,因为它的长度太长了随随便便都能10^9以上。。。木有办法只有通过不断的缩小查询区间,最后把所要求的那个数给查出来。
用一个len [maxn] 数组存储每次进行操作以后的长度。 对于每一次查询p,用二分查找,找到第一个大于等于p的len[i],其中i是操作数,如果t[i]=1 ,则直接返回a[k],就成,否则,则要不断的向前查找缩小查询范围。
不多说,下附代码
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdio>
using namespace std;
typedef unsigned long long ll;
const int maxn=100000+10;
ll len[maxn];
ll a[maxn],b[maxn];
int t[maxn];
ll n,m;
ll find(ll p)
{
int low=1,high=n;
while(low<high)
{
int mid=(low+high)/2;
if(p<=len[mid])
{
high=mid;
}
else
{
low=mid+1;
}
}
return low;
}
ll solve(ll p)
{
int k=find(p);
if(t[k]==1)
{
return a[k];
}
p-=len[k-1];
p%=a[k];
if(p==0)
{
p=a[k];
}
return solve(p);
}
int main()
{
while(scanf("%I64d",&n)!=EOF)
{
len[0]=0;
for(int i=1;i<=n;i++)
{
scanf("%d%I64d",&t[i],&a[i]);
if(t[i]==1)
{
len[i]=len[i-1]+1;
}
else
{
scanf("%I64d",&b[i]);
len[i]=len[i-1]+a[i]*b[i];
}
}
scanf("%I64d",&m);
for(int i=1;i<=m;i++)
{
if(i!=1)
{
printf(" ");
}
ll p;
scanf("%I64d",&p);
ll ans=solve(p);
printf("%I64d",ans);
}
printf("\n");
}
return 0;
}