1129 - 喵哈哈村的战斗魔法师丶坏坏い月
Time Limit:3s Memory Limit:256MByte
Submissions:542Solved:124
DESCRIPTION
坏坏い月是月大叔的ID,他是一个掌握者772002种魔法的物理系战士,最擅长的技能就是搞事。今天他又要开始搞事了。
给你nn个数,你需要实现一下操作:
-
l r v ,在[l,r]区间内找到第一个大于等于v的数,输出这个数的下标,如果找不到的话,请输出-1噢
-
l r v,让[l,r]区间所有数增加v
INPUT
输入第一行包含一个正整数
t(1≤t≤100)t(1≤t≤100) ,表示有t组数据对于每组数据:第一行包含两个整数
n(1≤n≤100000)n(1≤n≤100000),
q(1≤q≤100000)q(1≤q≤100000),表示数的个数,以及询问的个数。第二行包含
nn个整数
ai(1≤ai≤1000000000)ai(1≤ai≤1000000000)接下来q行,每行四个整数
opt(1≤opt≤2),l,r(1≤l≤r≤n),v(1≤v≤1000000000)opt(1≤opt≤2),l,r(1≤l≤r≤n),v(1≤v≤1000000000)
OUTPUT
对于每个询问,输出一行表示答案.
SAMPLE INPUT
1
5 3
1 2 3 4 5
1 1 2 3
2 1 2 3
1 1 2 3
SAMPLE OUTPUT
-1
1
SOLUTION
思路:
问题其实是在问,区间【L,R】内,第一个大于等于v这个数的最左边的位子。
那么我们其实可以二分加线段树查询区间最大值去做。时间复杂度为O(n*(logn)^2),logn约等于17.平方后约等于300.
这里学一下暴力分块。暴力分块其实就是将整个数组分成sqrt(n)块,然后维护几个数组即可,对于整块整块的更新值的时候,我们额外开出一个数组维护整块整块的提升的总价值和就能很好的解决这类更新和查询问题,时间复杂度O(nsqrt(n)),sqrt(n)为300+,约等于300.两种方法差不多,差在常数,肯定二分要快一些。
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long int
ll n,q,Len,tot;
ll a[150000],belong[150000];
ll L[500],R[500],maxn[500],Add[500];
void init()
{
memset(Add,0,sizeof(Add));
Len=(ll)sqrt(n);
tot=n/Len;if(n%Len!=0)tot++;
for(ll i=1;i<=n;i++)belong[i]=(i-1)/Len+1;
for(ll i=1;i<=tot;i++)L[i]=(i-1)*Len+1,R[i]=i*Len;
for(ll i=1;i<=n;i++)maxn[belong[i]]=max(maxn[belong[i]],a[i]);
}
void update(ll l,ll r,ll w)
{
ll LL=belong[l];
ll RR=belong[r];
if(LL==RR)
{
for(ll i=l;i<=r;i++)
{
a[i]+=w;
maxn[belong[i]]=max(maxn[belong[i]],a[i]+Add[belong[i]]);
}
}
else
{
for(ll i=l;i<=R[LL];i++)
{
a[i]+=w;
maxn[belong[i]]=max(maxn[belong[i]],a[i]+Add[belong[i]]);
}
for(ll i=L[RR];i<=r;i++)
{
a[i]+=w;
maxn[belong[i]]=max(maxn[belong[i]],a[i]+Add[belong[i]]);
}
for(ll i=LL+1;i<=RR-1;i++)
{
Add[i]+=w;
maxn[i]+=w;
}
}
}
ll query(ll l,ll r,ll w)
{
ll LL=belong[l];
ll RR=belong[r];
if(LL==RR)
{
for(ll i=l;i<=r;i++)
{
if(a[i]+Add[belong[i]]>=w)return i;
}
return -1;
}
for(ll i=l;i<=R[LL];i++)
{
if(a[i]+Add[belong[i]]>=w)return i;
}
for(ll i=LL+1;i<=RR-1;i++)
{
if(maxn[i]>=w)
{
for(ll j=L[i];j<=R[i];j++)
{
if(a[j]+Add[belong[j]]>=w)return j;
}
}
}
for(ll i=L[RR];i<=r;i++)
{
if(a[i]+Add[belong[i]]>=w)return i;
}
return -1;
}
int main()
{
ll t;
scanf("%d",&t);
while(t--)
{
scanf("%lld%lld",&n,&q);
for(ll i=1;i<=n;i++)scanf("%lld",&a[i]);
init();
while(q--)
{
ll op,x,y,z;
scanf("%lld%lld%lld%lld",&op,&x,&y,&z);
if(op==1)
{
printf("%lld\n",query(x,y,z));
}
if(op==2)
{
update(x,y,z);
}
}
}
}