魔音吉他
`魔音吉他
★问题描述
少年甲很喜欢音乐,有一天他来到了少年乙的村落。少年甲一曲高山流水,寻觅到了乙这位知音。然而,天下没有不散的宴席,少年甲要回村杀猪了,离别在即,少年乙拿出了自己珍藏多年的吉他,作为离别的礼物。就在少年甲欣喜之际,少年乙说,这把吉他变幻莫测,每次你拿起它的时候,它会有n根弦,每根弦可以演奏出 1e18+1
个音符,而这 1e18+1个音符是连续的,取决于它每根弦的第一个音符(请看样例说明)。 此时,少年甲提出了一个疑问,如果给定一个区间l,r(包括端点),里面共有几种不同的音符呢?少年乙对此谙熟于心,但是他想考验一下你,于是将这个问题抛给了你。
★数据输入
第一行一个正整数n(1<=n<=100,000),表示吉他有几根弦。 第二行共n个数x,即代表对应弦的第一个音符(0<=x<=10^18)。 第三行一个正整数q(1<=q<=100,000),表示少年甲的询问次数。 接下来q行,每行两个数l,r(0<=l,r<=10^18+1),表示少年甲想要询问的区间。
★数据输出
输出共q个数,表示对应q个询问的答案。即询问区间内有多少个不同的音符。以空格隔开。
★输入示例
6
3 1 4 1 5 9
3
7 7
0 2
8 17
★输出示例
5 10 18
★样例说明
列下标:0 1 2 3 4 5 …… 弦一:3 4 5 6 7 8 …… 弦二:1 2 3 4 5 6 …… 弦三:4 5 6 7 8 9 …… 弦四:1 2 3 4 5 6 …… 弦五:5 6 7 8 9 10 …… 弦六:9 10 11 12 13 14 ……
★Hint
(1)询问区间l,r即为样例说明中的列下标。 (2)所谓不同音符个数,即区间l,r内n行内不同的数字个数。 (3)由于l,r的范围巨大,请思考其与每行第一个数字的关系(即给出的第一个音符)。`
同学的代码WA(得4分)
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
ll const N=100010;
ll x[N];
ll y[N];
ll z[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
ll n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>x[i];
}
int q;
cin>>q;
ll r[q];
ll l[q];
ll s[q];
for(int i=0;i<q;i++)
{
cin>>l[i]>>r[i];
s[i]=r[i]-l[i]+1;
}
sort(x+1,x+n+1);
for(int i=1;i<n;i++)
{
y[i]=x[i+1]-x[i];
}
sort(y+1,y+n);
for(int i=1;i<n;i++)
{
z[i]=z[i-1]+y[i];
}
ll ans[q];
for(int i=0;i<q;i++)
{
ll sp = upper_bound(y+1,y+n,s[i]) - y-1;//从数组的begin位置到end-1位置二分查找第一个大于num的数字,
//找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
ans[i]=z[sp]+(n-sp)*s[i];
}
for(int i=0;i<q;i++)
{
cout<<ans[i]<<" ";
}
return 0;
}
我的代码 (超时 4分)
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=100010;
int main()
{
ios::sync_with_stdio(false);
ll n;
cin>>n;
ll *x=new ll[n];
for(int i=0;i<n;i++)
{
cin>>x[i];
}
int q;
cin>>q;
ll r[q];
ll l[q];
ll s[q];
for(int i=0;i<q;i++)
{
cin>>l[i]>>r[i];
s[i]=r[i]-l[i];
}
sort(x+0,x+n);
int len = unique(x,x+n)-x;//去重排序
ll ans = 0;
ll index = 0;
ll forw = 0;
for(int i=0;i<q;i++)
{
ans = 0;
index = x[0]+s[i];
forw = x[0];
for(int j=1;j<=len;j++)
{
if(index>=(x[j]))
{
index = x[j]+s[i];
}
else
{
ans+=index-forw+1;
index = x[j]+s[i];
forw = x[j];
}
}
ans += index-forw+1;
cout<<ans<<" ";
}
delete []x;
return 0;
}
求求各位大佬有空帮个忙,在线帮忙测,谢谢。