周末UA做了這場多校的vjudge版本。
我去陪爸媽去山溝溝轉了,回來聽說有個這個線段樹,想敲敲。
多年不做線段樹,好噁心><
struct Tnode{// 一維線段樹 int l,r; int cover; int lid, rid; int sum; int len() { return r - l;} int mid() { return MID(l,r);} bool in(int ll,int rr) { return l >= ll && r <= rr; } void lr(int ll,int rr){ l = ll; r = rr;}};
這個是我每次都用的線段樹定義,根據題目不同,會更改一些標記。
根據這個題來說,cover = 0表示該區間的位置都為空白,cover=1表示該區間都不為空白,cover=-1表示部分為空白(借鑒於zoj線段覆蓋那道題)
sum表示該區間裡為空白的位置長度和。
lid表示該區間最左邊為空白的位置號,rid為最右邊為空白的位置號。若sum = 0,則lid rid都為-1。
操作1:
輸入a ,b
比較麻煩,求左端點很簡單,直接查詢下就行了。求出左端點lpos。若為-1輸出Can not balabala。。
求右端點的時候我是先求出0~lpos中間的空位置val,然後求從0~n-1中空位置大於等於val+b的位置。方便分。
因為糾結一點,不知道如何在區間[l,r]中尋找空位置為d的位置(就我目前維護的標記來說),但是尋找[0,r]的位置會很easy~懂吧?
操作2:
求個sum即可
出錯地方:查左端點的時候,如果左邊查不到,那麼右邊得查,我直接左邊差不到就返回了。要知道如果[l,r]區間中有sum>0的位置,但是空位置不一定是在需要的區間中。
比如區間[0, 9]中有空位置[0,1]和[5,6],但是呢,我需要的是[3, 6]中的空位置,顯然mid後,左邊[0,5]有空位置,但是是找不到對應的在[3,6]的空位置的。改過就過了。
時間:C++,400+MS,估計是用指標了,慢了,但是真心不習慣用數組替代,唉唉唉。
#include <set>#include <map>#include <queue>#include <stack>#include <math.h>#include <stdio.h>#include <stdlib.h>#include <iostream>#include <limits.h>#include <string.h>#include <string>#include <algorithm>#define MID(x,y) ( ( x + y ) >> 1 )#define L(x) ( x << 1 )#define R(x) ( x << 1 | 1 )#define FOR(i,s,t) for(int i=(s); i<(t); i++)#define FORD(i,s,t) for(int i=(s-1); i>=t; i--)#define BUG puts("here!!!")#define STOP system("pause")#define file_r(x) freopen(x, "r", stdin)#define file_w(x) freopen(x, "w", stdout)using namespace std;const int MAX = 50010;struct Tnode{// 一維線段樹 int l,r; int cover; int lid, rid; int sum; int len() { return r - l;} int mid() { return MID(l,r);} bool in(int ll,int rr) { return l >= ll && r <= rr; } void lr(int ll,int rr){ l = ll; r = rr;}};Tnode node[MAX<<2];void Update_sum(int t){node[t].sum = node[R(t)].sum + node[L(t)].sum;if( node[L(t)].lid != -1 )node[t].lid = node[L(t)].lid;elsenode[t].lid = node[R(t)].lid;node[t].rid = max(node[L(t)].rid, node[R(t)].rid);if( node[t].sum == 0 )node[t].cover = 1;elseif( node[t].sum == node[t].len() )node[t].cover = 0;elsenode[t].cover = -1;}void Build(int t,int l,int r){node[t].lr(l,r);node[t].lid = l;node[t].rid = r;node[t].sum = node[t].len();node[t].cover = 0;if( node[t].len() == 1 )return ;int mid = MID(l,r);Build(L(t),l,mid);Build(R(t),mid,r);}void update_cover(int t) {if( node[t].cover == -1 )return ;if( node[t].cover == 1 ) {node[t].sum = 0;node[t].lid = -1;node[t].rid = -1;} else {node[t].sum = node[t].len();node[t].lid = node[t].l;node[t].rid = node[t].r;}}void push_cover(int t) {if( node[t].len() == 1 ) return ;if( node[t].cover != -1 ) {node[L(t)].cover = node[R(t)].cover = node[t].cover;update_cover(L(t));update_cover(R(t));}}void Update(int t,int l,int r,int val){push_cover(t);if( node[t].in(l,r) ){node[t].cover = val;update_cover(t);return ;}if( node[t].len() == 1 ) return ;int mid = node[t].mid();if( l < mid ) Update(L(t),l,r,val);if( r > mid ) Update(R(t),l,r,val);Update_sum(t);}int Query(int t,int l,int r){push_cover(t);if( node[t].in(l,r) )return node[t].sum;if( node[t].len() == 1 ) return 0;int mid = node[t].mid();int ans = 0;if( l < mid ) ans += Query(L(t),l,r);if( r > mid ) ans += Query(R(t),l,r);return ans;}int Querylid(int t,int l,int r){push_cover(t);if( node[t].in(l,r) && node[t].sum > 0 )return node[t].lid;if( node[t].len() == 1 ) return -1;int mid = node[t].mid();if( l < mid && node[L(t)].sum > 0 ) {int pos = Querylid(L(t),l,r);if( pos != -1 )return pos;}if( r > mid && node[R(t)].sum > 0 )return Querylid(R(t),l,r);return -1;}int Queryrid(int t,int l, int r, int val){push_cover(t);if( node[t].sum <= val )return node[t].rid;if( node[t].len() == 1 ) return -1;int mid = node[t].mid();if( l < mid && node[L(t)].sum >= val )return Queryrid(L(t), l, r, val);if( r > mid && node[R(t)].sum > 0 )return Queryrid(R(t), l, r, val - node[L(t)].sum);return -1;}int main() {int ncases, n, m;int opera, a, b;scanf("%d", &ncases);while( ncases-- ) {scanf("%d%d", &n, &m);if( m > 0 ) Build(1, 0, n);while( m-- ) {scanf("%d%d%d", &opera, &a, &b);if( opera == 1 ) {int lpos = Querylid(1, a, n);if( lpos == -1 ) {puts("Can not put any one.");continue;}int val = Query(1, 0, lpos);int rpos = Queryrid(1, 0, n, b + val);printf("%d %d\n", lpos, rpos-1);Update(1, lpos, rpos, 1);}if( opera == 2 ) {if( b > n )b = n - 1;int ans = Query(1, a, b+1);Update(1, a, b+1, 0);printf("%d\n", b - a + 1 - ans);}}puts("");}return 0;}