BZOJ 3110

很早就想写的试炼场题。

不会整体二分啊呜呜呜,只能写写树套树。

有一个trick就是外层使用一个权值线段树,把位置作为下标的线段树放在内层,这样子的话我们在查询$k$大的时候就可以直接在外层线段树上一边走一边二分。

注意我们查询的是第$k$大不是第$k$小,所以我们在走的时候要观察右子树的权值和$k$的关系。

内层可以动态开点防mle,注意在打标记下传的时候要先给左右儿子赋值。

挺卡常的。

时间复杂度$O(nlog^2n)$。

Code:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll; const int N = 5e4 + ; int n, qn, mn, tot = ;
ll val[N]; struct Querys {
int type, l, r;
ll k;
} q[N]; template <typename T>
inline void read(T &X) {
X = ; char ch = ; T op = ;
for(; ch > ''|| ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} namespace SegT {
struct Node {
int lc, rc, tag;
ll sum;
} s[N * ]; int root[N << ], nodeCnt = ; #define lc(p) s[p].lc
#define rc(p) s[p].rc
#define sum(p) s[p].sum
#define tag(p) s[p].tag
#define mid ((l + r) >> 1) inline void up(int p) {
if(!p) return;
sum(p) = sum(lc(p)) + sum(rc(p));
} inline void down(int p, int l, int r) {
if(!tag(p)) return;
if(!lc(p)) lc(p) = ++nodeCnt;
if(!rc(p)) rc(p) = ++nodeCnt;
sum(lc(p)) += 1LL * tag(p) * (mid - l + ), tag(lc(p)) += tag(p);
sum(rc(p)) += 1LL * tag(p) * (r - mid), tag(rc(p)) += tag(p);
tag(p) = ;
} void ins(int &p, int l, int r, int x, int y) {
if(!p) p = ++nodeCnt;
if(x <= l && y >= r) {
++tag(p);
sum(p) += 1LL * (r - l + );
return;
} down(p, l, r);
if(x <= mid) ins(lc(p), l, mid, x, y);
if(y > mid) ins(rc(p), mid + , r, x, y);
up(p);
} ll getSum(int p, int l, int r, int x, int y) {
if(!p) return 0LL;
if(x <= l && y >= r) return sum(p); down(p, l, r); ll res = 0LL;
if(x <= mid) res += getSum(lc(p), l, mid, x, y);
if(y > mid) res += getSum(rc(p), mid + , r, x, y);
return res;
} void modify(int p, int l, int r, int x, int y, int v) {
ins(root[p], , n, x, y);
if(l == r) return; if(v <= mid) modify(p << , l, mid, x, y, v);
else modify(p << | , mid + , r, x, y, v);
} int query(int p, int l, int r, int x, int y, ll k) {
if(l == r) return l; ll now = getSum(root[p << | ], , n, x, y);
if(now >= k) return query(p << | , mid + , r, x, y, k);
else return query(p << , l, mid, x, y, k - now);
} } using namespace SegT; int main() {
read(n), read(qn);
for(int i = ; i <= qn; i++) {
read(q[i].type), read(q[i].l), read(q[i].r), read(q[i].k);
if(q[i].type == ) val[++tot] = q[i].k;
} sort(val + , val + tot + );
tot = unique(val + , val + + tot) - val - ;
mn = tot; for(int i = ; i <= qn; i++) {
if(q[i].type == ) {
int v = lower_bound(val + , val + + tot, q[i].k) - val;
modify(, , mn, q[i].l, q[i].r, v);
} else printf("%lld\n", val[query(, , mn, q[i].l, q[i].r, q[i].k)]);
} return ;
}

最新文章

  1. Intellij IDEA 一些不为人知的技巧
  2. oracle当前的连接数
  3. Spring Collections XML 配置
  4. 指定的参数已超出有效值的范围 参数名: utcDate WebResource异常
  5. Codevs
  6. BCB6中SCALERICHVIEW加入GIF动画
  7. django - transaction
  8. JPush 极光推送 消息推送 实例
  9. 2017中国数据库技术大会(DTCC)又要来啦!期待~~
  10. 转载-ACPI的知识
  11. JAVA课程设计 猜数游戏 团队
  12. C# Ioc 接口注册实例以及注入MVC Controller
  13. Tomcat启动出现:Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/SpringMvc]]解决办法
  14. Struts(十四):通用标签-form表单
  15. Flask实战第3天:url_for使用
  16. ntp服务
  17. “多个单核CPU”与“单个多核CPU”哪种方式性能较强?
  18. Docker概念(二)
  19. 微信开发之获取openid及推送模板消息
  20. unidac记录日志

热门文章

  1. http请求 详解
  2. Android Volley完全解析(二),使用Volley加载网络图片
  3. java web service 上传下载文件
  4. C#异步编程(五)异步的同步构造
  5. python沉淀之路~~整型的属性
  6. 类和对象(9)—— new和delete
  7. 微信小程序编写物流信息进度样式
  8. unity3d___UGui中如何创建loading...进度条
  9. 2、配置Selenium RC
  10. SpringCloud微服务实战——第一章序言读书笔记