玲珑oj 1129 ST

1129 - 喵哈哈村的战斗魔法师丶坏坏い月

Time Limit:3s Memory Limit:256MByte

Submissions:490Solved:107

DESCRIPTION

坏坏い月是月大叔的ID,他是一个掌握者772002种魔法的物理系战士,最擅长的技能就是搞事。今天他又要开始搞事了。

给你n

个数,你需要实现一下操作:

  1. l r v ,在[l,r]区间内找到第一个大于等于v的数,输出这个数的下标,如果找不到的话,请输出-1噢

  2. l r v,让[l,r]区间所有数增加v

INPUT
输入第一行包含一个正整数 t(1t100)

,表示有t组数据 对于每组数据: 第一行包含两个整数n(1n100000),q(1q100000),表示数的个数,以及询问的个数。 第二行包含n个整数 ai(1ai1000000000) 接下来q行,每行四个整数opt(1opt2),l,r(1lrn),v(1v1000000000)

 
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
线段树区间修改,用lazy标记处理,由于我在ask()函数写的不是进行的二分查找而是两边都查找导致TLE,后来改了才AC,可见细节的重要性,
如果在左边找到了满足条件的数则可以放弃右边的查找否则两边都要找。
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4 #define MAXN ((100000<<2)+15)
 5 struct SegTree
 6 {
 7     #define lc (id<<1)
 8     #define rc (id<<1|1)
 9     #define M  ((L+R)>>1)
10     LL Max[MAXN],Add[MAXN];
11     void init()
12     {
13         memset(Max,0,sizeof(Max));
14         memset(Add,0,sizeof(Add));
15     }
16     void pushdown(int L,int R,int id)
17     {
18         if(!Add[id]) return;
19         Add[lc]+=Add[id];
20         Add[rc]+=Add[id];
21         Max[lc]+=Add[id];
22         Max[rc]+=Add[id];
23         Add[id]=0;
24     }
25     void build(int L,int R,int id)
26     {
27         if(L==R){scanf("%lld",&Max[id]);return;}
28         build(L,M,lc);
29         build(M+1,R,rc);
30         Max[id]=max(Max[lc],Max[rc]);
31     }
32     void update(int L,int R,int id,int l,int r,int v)
33     {
34         if(L>=l&&R<=r){
35             Max[id]+=v;
36             Add[id]+=v;
37             return;
38         }
39         pushdown(L,R,id);
40         if(l<=M) update(L,M,lc,l,r,v);
41         if(r>M)  update(M+1,R,rc,l,r,v);
42         Max[id]=max(Max[lc],Max[rc]);
43     }
44     int ask(int L,int R,int id,int l,int r,int v)
45     {
46         if(Max[id]<v) return -1;
47         if(L==R){
48             if(!(L>=l&&R<=r)) return -1;
49             if(Max[id]<v) return -1;
50             else return L;
51         }
52         pushdown(L,R,id);
53         Max[id]=max(Max[lc],Max[rc]);
54         int ans=-1,y=-1;
55         if(l<=M) ans=ask(L,M,lc,l,r,v);
56         if(ans!=-1) return ans;
57         if(r>M) y=ask(M+1,R,rc,l,r,v);
58         return y;
59     } 
60 }seg;
61 int main()
62 {
63     int t,n,m,i,j,k,opt,l,r,v;
64     scanf("%d",&t);
65     while(t--){
66         scanf("%d%d",&n,&m);
67         seg.init();
68         seg.build(1,n,1);
69         while(m--){
70             scanf("%d%d%d%d",&opt,&l,&r,&v);
71             if(opt==1){
72                 printf("%d\n",seg.ask(1,n,1,l,r,v));
73             }
74             else{
75                 seg.update(1,n,1,l,r,v);
76             }
77         }
78     }
79     return 0;
80 }

 

转载于:https://www.cnblogs.com/zzqc/p/7283534.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值