1129
来源:互联网 发布:json中包含html标签 编辑:程序博客网 时间:2024/05/16 10:12
题意:n个数,有q次询问,每次询问有两个操作 1.在区间【l, r】找到比v大的第一个数的下标 2.把【l,r】的数全部加上v。
思路: 裸线段树的题
写法1:线段树
#include <cstdio>#include <cstring>#include <iostream>#define mem(a) memset(a, 0, sizeof(a))using namespace std;const int inf = 0x3f3f3f3f;const int MAXN =100100;typedef long long LL;LL a[MAXN];LL lazy[MAXN<<2];struct T{ int l, r; LL m;} tree[MAXN<<2];void pushdown(int k){ if(lazy[k]) { tree[k<<1].m+=lazy[k]; tree[k<<1|1].m+=lazy[k]; lazy[k<<1]+=lazy[k]; lazy[k<<1|1]+=lazy[k]; lazy[k]=0; } return ;}void pushup(int k){ tree[k].m=max(tree[k<<1].m, tree[k<<1|1].m);}void build(int l, int r, int k){ tree[k].l=l; tree[k].r=r; tree[k].m=0; if(l==r) { tree[k].m=a[l]; return; } int mid = (l+r)>>1; build(l, mid, k<<1); build(mid+1, r, k<<1|1); pushup(k);}void update(int l, int r, int k, LL w){ if(tree[k].l>=l&&tree[k].r<=r) { tree[k].m+=w; lazy[k]+=w; return; } pushdown(k); int mid = (tree[k].l+tree[k].r)>>1;// if(l<=mid)// update(l, r, k<<1, w);// if(r>mid)// update(l, r, k<<1|1, w);//两种写法都可以。 if(l>mid) update(l, r, k<<1|1, w); else if(r<=mid) update(l,r,k<<1,w); else { update(l, mid, k<<1, w); update(mid+1, r, k<<1|1, w); } pushup(k); return ;}int query(int l, int r, int k, LL c){ if(tree[k].m<c) return -1; if(tree[k].l==tree[k].r) return tree[k].l; pushdown(k); pushup(k); int mid = (tree[k].l+tree[k].r)>>1; int x=-1, y=-1; if(l<=mid) x=query(l, r, k<<1, c); if(x!=-1)return x; if(r>mid) y=query(l, r, k<<1|1, c); return y;}int main(){ int t, q; scanf("%d",&t); while(t--) { int n; memset(lazy, 0, sizeof(lazy)); scanf("%d %d",&n, &q); for(int i=1; i<=n; ++i) scanf("%lld", &a[i]); build(1, n, 1); int op, l, r; LL v; while(q--) { scanf("%d %d %d %lld", &op, &l,&r, &v); if(op==1) printf("%d\n", query(l, r, 1, v)); else update(l, r, 1, v); } } return 0;}
写法二:分块
#include <bits/stdc++.h>using namespace std;const int MAXN = 100005;typedef long long LL;LL a[MAXN], b[MAXN];LL add[MAXN], mx[MAXN];int n, block;void init(){ block = sqrt(n); int num = n/block; for(int i=1; i<=num; ++i) for(int j=(i-1)*block+1; j<=i*block; ++j) mx[i]=max(a[j], mx[i]);//维护每一块的最大值 if(n%num) num++;//如果不湿刚好分完块 for(int i=num; i<=num; ++i) for(int j=(num-1)*block+1; j<=n; ++j) mx[i]=max(a[j],mx[i]);//对最后一块找最大// for(int i=1;i<=num;++i)// printf("%lld\n", mx[i]); for(int i=1; i<=n; ++i) b[i]=(i-1)/block+1;//标记下标i在第几块}void update(int l,int r,LL k){ int lq=b[l]; int rq=b[r]; //printf("%d %d\n", b[l], b[r]); if(lq==rq)//如果在同一块, 暴力sqrt(n)更新 { for(int i=l; i<=r; i++) { a[i]+=k; if(a[i]+add[lq]>mx[lq]) mx[lq]=a[i]+add[lq]; } return ; } for(int i=l; i<=lq*block; i++) { a[i]+=k; if(a[i]+add[lq]>mx[lq]) mx[lq]=a[i]+add[lq]; } for(int i=(rq-1)*block+1; i<=r; i++) { a[i]+=k; if(a[i]+add[rq]>mx[rq]) mx[rq]=a[i]+add[rq]; } //如果区间跨度大于两块,也就是r-l>1,直接更新块(分块的核心) if(rq-lq>1) { for(int i=lq+1; i<rq; i++) { add[i]+=k; mx[i]+=k; } }}LL query(int l,int r,LL k){ int lq=b[l]; int rq=b[r]; if(lq==rq)//只有一块 { for(int i=l; i<=r; i++) { if(a[i]+add[lq]>=k) return i; } return -1; } //从左向右找,找到直接返回下标 for(int i=l; i<=lq*block; i++) { if(a[i]+add[lq]>=k) return i; } if(rq-lq>1)//有多块 { for(int i=lq+1; i<rq; i++) { if(mx[i]>=k) { for(int j=(i-1)*block+1; j<=i*block; j++) { if(a[j]+add[i]>=k) return j; } } } } for(int i=(rq-1)*block+1; i<=r; i++) { if(a[i]+add[rq]>=k) return i; } return -1;}int main(){ int t; scanf("%d", &t); while(t--) { int q; memset(add, 0, sizeof(add)); memset(mx, 0, sizeof(mx)); scanf("%d %d", &n, &q); for(int i=1; i<=n; ++i) scanf("%lld", &a[i]); init(); while(q--) { int op, l,r; LL k; scanf("%d%d%d%lld",&op,&l,&r,&k); if(op==1) printf("%lld\n",query(l,r,k)); else { update(l,r,k);// for(int i=1;i<=n;++i)// printf("%lld%c", a[i]+add[b[i]], " \n"[i==n]); } } } return 0;}
阅读全文
0 0
- 1129
- 1129
- 1129
- 1129
- 1129
- 1129
- 1129
- 1129 WSADATA
- 1129: Divisibility
- POJ 1129
- sicily 1129
- HDOJ 1129
- POJ 1129
- poj 1129
- poj--1129
- POJ 1129
- POJ 1129
- PKU 1129
- python中使用xlrd、xlwt操作excel表格详解
- 设计模式——观察者监听者模式
- 算法练习
- EventBus的使用
- 大话数据结构 code 第八章 05散列表_HashTable
- 1129
- 第10天(08.09)
- 什么是javaBean,pojo,EJB
- 8.9 马蹄印 2493
- 对 Android 应用程序包进行签名
- linux Device Tree Usage
- camera平滑移动
- MySQL
- C++ STL set/multset