Vases and Flowers (二分 + 线段树)

题目链接:https://vjudge.net/contest/332656#problem/H

 

 题意:

n个花瓶,m个操作,花瓶里面有的有花,有的是空的。

1 x y 表示从第x个位置开始查y多花,若一朵花也插不上输出"Can not put any one.",反之输出插花的左位置和右位置。

2 操作是清除区间[a,b]的花。并输出清除了多少花。

 

思路:
线段树维护区间,然后每次二分查找满足要求的第一个位置。

 

  1 #include 
  2 #include 
  3 #include 
  4 #include 
  5 #include 
  6 #include <string>
  7 #include <string.h>
  8 #include 
  9 #include 
 10 #include 
 11 #include <set>
 12 #include 
 13 
 14 #define ll long long
 15 const int maxn = 1e5 + 10;
 16 
 17 int n,m;
 18 
 19 struct Node {
 20     int l,r;
 21     int val;
 22     int lazy;
 23 }tree[maxn<<2];
 24 
 25 void build(int l,int r,int nod) {
 26     tree[nod].l = l;
 27     tree[nod].r = r;
 28     if (l == r ) {
 29         tree[nod].lazy = -1;
 30         return ;
 31     }
 32     int mid = (l + r) >> 1;
 33     build(l,mid,nod<<1);
 34     build(mid+1,r,(nod<<1)+1);
 35 }
 36 
 37 void pushdown(int nod) {
 38     tree[nod<<1].val = tree[nod].lazy*(tree[nod<<1].r-tree[nod<<1].l+1);
 39     tree[(nod<<1)+1].val = tree[nod].lazy*(tree[(nod<<1)+1].r-tree[(nod<<1)+1].l+1);
 40     tree[nod<<1].lazy = tree[(nod<<1)+1].lazy = tree[nod].lazy;
 41     tree[nod].lazy = -1;
 42 }
 43 
 44 void modify(int x,int y,int z,int nod=1) {
 45     int l = tree[nod].l,r = tree[nod].r;
 46     if (x <= l && y >= r) {
 47         tree[nod].lazy = z;
 48         tree[nod].val = (r-l+1)*z;
 49         return ;
 50     }
 51     if (tree[nod].lazy != -1 ) {
 52         pushdown(nod);
 53     }
 54     int mid = (l + r) >> 1;
 55     if (x <= mid) {
 56         modify(x,y,z,nod<<1);
 57     }
 58     if (y > mid) {
 59         modify(x,y,z,(nod<<1)+1);
 60     }
 61     tree[nod].val = tree[nod<<1].val + tree[(nod<<1)+1].val;
 62 }
 63 
 64 int query(int x,int y,int nod=1) {
 65     int l = tree[nod].l,r = tree[nod].r;
 66     if (x <= l && y >= r) {
 67         return tree[nod].val;
 68     }
 69     if (tree[nod].lazy != -1 ) {
 70         pushdown(nod);
 71     }
 72     int mid = (l + r ) >> 1;
 73     int sum = 0;
 74     if (x <= mid) {
 75         sum += query(x,y,nod<<1);
 76     }
 77     if (y > mid) {
 78         sum += query(x,y,(nod<<1)+1);
 79     }
 80     tree[nod].val = tree[nod<<1].val + tree[(nod<<1)+1].val;
 81     return sum;
 82 }
 83 
 84 int find(int s,int num ) {  // 查找满足从s开始插入num个的右边第一个位置
 85     int temp = query(s,n,1);
 86     if (temp == n-s+1) {
 87         return -1;
 88     }
 89     if (n-s+1-temp < num) {
 90         num = n-s+1-temp;
 91     }
 92     int l = s,r = n;
 93     int mid,d;
 94     int f = -1;
 95     while (l <= r) {
 96         mid = (l + r) >> 1;
 97         d = mid-s+1-query(s,mid);
 98         if (d > num) {
 99             r = mid - 1;
100         }
101         else if (d < num) {
102             l = mid + 1;
103         }
104         else {
105             f = mid;
106             r = mid - 1;
107         }
108     }
109     return f;
110 }
111 
112 int main() {
113     int T;
114     scanf("%d",&T);
115     while (T--) {
116         memset(tree,0, sizeof(tree));
117         scanf("%d%d",&n,&m);
118         n--;
119         build(0,n,1);
120         while (m--) {
121             int d,x,y;
122             scanf("%d%d%d",&d,&x,&y);
123             if (d == 1) {
124                 int temp = find(x,1);
125                 if (temp == -1) {
126                     printf("Can not put any one.\n");
127                 }
128                 else {
129                     int end = find(x,y);
130                     printf("%d %d\n",temp,end);
131                     modify(temp,end,1);
132                 }
133             }
134             else {
135                 printf("%d\n",query(x,y));
136                 modify(x,y,0);
137             }
138         }
139         printf("\n");
140     }
141     return 0;
142 }

 

你可能感兴趣的:(Vases and Flowers (二分 + 线段树))