博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[SHOI2015]脑洞治疗仪
阅读量:5337 次
发布时间:2019-06-15

本文共 3379 字,大约阅读时间需要 11 分钟。

这题其实就是一个线段树维护最大连续和的水题。
别的操作不说,操作1只要二分找区间前\(k\)个0即可。
需要注意的是,因为操作1两区间可能有交,因此要先清空再二分查询……
复杂度\(O(n log ^ 2 n)\)

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;#define enter puts("") #define space putchar(' ')#define Mem(a, x) memset(a, x, sizeof(a))#define In inlinetypedef long long ll;typedef double db;const int INF = 0x3f3f3f3f;const db eps = 1e-8;const int maxn = 2e5 + 5;inline ll read(){ ll ans = 0; char ch = getchar(), last = ' '; while(!isdigit(ch)) last = ch, ch = getchar(); while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar(); if(last == '-') ans = -ans; return ans;}inline void write(ll x){ if(x < 0) x = -x, putchar('-'); if(x >= 10) write(x / 10); putchar(x % 10 + '0');}int n, m;struct Tree{ int l, r, sum, lzy; int lmax, rmax, imax; In Tree operator + (const Tree& oth)const { Tree ret; ret.l = l, ret.r = oth.r; ret.sum = sum + oth.sum, ret.lzy = -1; ret.lmax = lmax; if(ret.lmax == r - l + 1) ret.lmax += oth.lmax; ret.rmax = oth.rmax; if(ret.rmax == oth.r - oth.l + 1) ret.rmax += rmax; ret.imax = max(max(imax, oth.imax), rmax + oth.lmax); return ret; }}t[maxn << 2];In void build(int L, int R, int now){ t[now].l = L, t[now].r = R; t[now].lzy = -1; if(L == R) {t[now].sum = 1;return;} int mid = (L + R) >> 1; build(L, mid, now << 1); build(mid + 1, R, now << 1 | 1); t[now] = t[now << 1] + t[now << 1 | 1];}In void change(int now, int d){ t[now].sum = (t[now].r - t[now].l + 1) * d; t[now].lzy = d; t[now].lmax = t[now].rmax = t[now].imax = (t[now].r - t[now].l + 1) * (d ^ 1);}In void pushdown(int now){ if(~t[now].lzy) { change(now << 1, t[now].lzy), change(now << 1 | 1, t[now].lzy); t[now].lzy = -1; }}In void update(int L, int R, int now, int d){ if(t[now].l == L && t[now].r == R) {change(now, d); return;} pushdown(now); int mid = (t[now].l + t[now].r) >> 1; if(R <= mid) update(L, R, now << 1, d); else if(L > mid) update(L, R, now << 1 | 1, d); else update(L, mid, now << 1, d), update(mid + 1, R, now << 1 | 1, d); t[now] = t[now << 1] + t[now << 1 | 1];}In int query_sum(int L, int R, int now){ if(t[now].l == L && t[now].r == R) return t[now].sum; pushdown(now); int mid = (t[now].l + t[now].r) >> 1; if(R <= mid) return query_sum(L, R, now << 1); else if(L > mid) return query_sum(L, R, now << 1 | 1); else return query_sum(L, mid, now << 1) + query_sum(mid + 1, R, now << 1 | 1);}In Tree query_con(int L, int R, int now){ if(t[now].l == L && t[now].r == R) return t[now]; pushdown(now); int mid = (t[now].l + t[now].r) >> 1; if(R <= mid) return query_con(L, R, now << 1); else if(L > mid) return query_con(L, R, now << 1 | 1); else return query_con(L, mid, now << 1) + query_con(mid + 1, R, now << 1 | 1);}int main(){ n = read(), m = read(); build(1, n, 1); for(int i = 1; i <= m; ++i) { int op = read(), l1 = read(), r1 = read(); if(op == 0) update(l1, r1, 1, 0); else if(op == 2) write(query_con(l1, r1, 1).imax), enter; else { int l2 = read(), r2 = read(); int sum = query_sum(l1, r1, 1); update(l1, r1, 1, 0); if(!sum) continue; int L = l2, R = r2; while(L < R) { int mid = (L + R) >> 1; if(mid - l2 + 1 - query_sum(l2, mid, 1) >= sum) R = mid; else L = mid + 1; } update(l2, L, 1, 1); } } return 0;}

转载于:https://www.cnblogs.com/mrclr/p/10607136.html

你可能感兴趣的文章
子串的替换
查看>>
linux中常用的60个命令及作用详解
查看>>
poj 1664放苹果(递归)
查看>>
CDN、浏览器缓存
查看>>
Python+opencv图像识别
查看>>
字节流VS缓冲流
查看>>
也谈用友被面试经历【去年杭州用友被拒】
查看>>
伴随开发人员成长的问题:工程重要,还是算法重要?细节重要,还是架构重要?...
查看>>
GTK添加事件
查看>>
linux----tail 过滤日志文件中的关键字
查看>>
图论最短路径例题
查看>>
C#设计模式——适配器模式(Adapter Pattern)
查看>>
計蒜客/小教官(xjb)
查看>>
Linux文件和目录
查看>>
Faster_RCNN 2.模型准备(上)
查看>>
ANDROID 2.0游戏开发实战宝典pdf
查看>>
《Android 4高级编程(第3版)》(完整书签).pdf
查看>>
pku 2195 Going Home 最小费最大流问题
查看>>
第四届ACM_DIY群程序设计竞赛 (部分解题报告) 弱菜在此大牛无视。。。
查看>>
通货膨胀 通货紧缩 贸易逆差
查看>>