题目链接:http://ifrog.cc/acm/problem/1129
思路就是用线段树查找最左边第一个大于等于v的数,然后返回线段树下表即可。
代码如下:
#include<bits/stdc++.h>
using namespace std;
struct node
{
int l, r;
long long x, add;
};
node tree[1000000 << 3];
void build(int l, int r, int k)
{
tree[k].l = l, tree[k].r = r, tree[k].add = 0;
if(l == r)
{
scanf("%lld", &tree[k].x);
return ;
}
int mid = (l + r) >> 1;
build(l, mid, k<<1);
build(mid+1, r, k<<1|1);
tree[k].x = max(tree[k<<1].x, tree[k<<1|1].x);
}
int query(int l, int r, int k, long long x)
{
if(tree[k].l <= l && tree[k].r >= r)
{
if(tree[k].x < x)
return -1;
}
if(tree[k].l == tree[k].r)
return tree[k].l;
if(tree[k].add)
{
tree[k<<1].x += tree[k].add, tree[k<<1|1].x += tree[k].add;
tree[k<<1].add += tree[k].add, tree[k<<1|1].add += tree[k].add;
tree[k].add = 0;
}
int res = -1;
if(tree[k<<1].r >= l && tree[k<<1].x >= x)
res = query(l, r, k<<1, x);
if(res != -1)
return res;
if(tree[k<<1|1].l <= r && tree[k<<1|1].x >= x)
res = query(l, r, k<<1|1, x);
return res;
}
void updata(int l, int r, int k, long long x)
{
if(tree[k].l >= l && tree[k].r <= r)
{
tree[k].x += x;
tree[k].add += x;
return ;
}
if(tree[k].add)
{
tree[k<<1].x += tree[k].add, tree[k<<1|1].x += tree[k].add;
tree[k<<1].add += tree[k].add, tree[k<<1|1].add += tree[k].add;
tree[k].add = 0;
}
if(tree[k<<1].r >= l)
updata(l, r, k<<1, x);
if(tree[k<<1|1].l <= r)
updata(l, r, k<<1|1, x);
tree[k].x = max(tree[k<<1].x, tree[k<<1|1].x);
}
void solve()
{
int n, q;
scanf("%d %d", &n, &q);
build(1, n, 1);
for(int i=0, op, l, r; i<q; ++ i)
{
long long v;
scanf("%d %d %d %lld", &op, &l, &r, &v);
if(op == 1)
printf("%d
", query(l, r, 1, v));
else
updata(l, r, 1, v);
}
}
int main()
{
int t;
scanf("%d", &t);
while(t --)
solve();
return 0;
}