HDU #5283 Senior's Fish

题目描述:

平面上有一些鱼,初始时鱼会在一些位置,某些时刻编号在一段区间内的鱼会同时向x轴正方向,或y轴正方向平移一定距离,某些时刻会询问一个矩形内鱼的数量。

解题思路:

显然地,求一个矩形内的鱼可以用矩形四个顶点为右上角的整个左下矩形加加减减。那么问题就转化为一个顶点左下角矩形内鱼的数量。注意到鱼只会向右和向上的话,那就很好做。维护两颗线段树,分别维护编号在l~r的鱼的x坐标最大值、y坐标最大值。每次修改对应区间加。每次如果区间最大值大于限制,那就找出最大值的位置,赋为-inf,同时在树状数组删掉改点就可以了。询问就在树状数组上询问区间点的数量。

代码:

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 using namespace std;
  5
  6 const int N = 3e4 + 10, inf = 1e9 + 1;
  7 int T, n, m, x1, y1, x2, y2, fis[N][2], ans[N], sum[N];
  8
  9 struct que{int s, l, r, d;} q[N];
 10
 11 struct node{int mx, tag;} tx[N * 8], ty[N * 8];
 12
 13 int lowbit(int x) {return x & -x;}
 14
 15 void add(int x, int v) {
 16     while (x <= N - 10) sum[x] += v, x += lowbit(x);
 17 }
 18
 19 int Sum(int x) {
 20     int r = 0;
 21     while (x) r += sum[x], x -= lowbit(x);
 22     return r;
 23 }
 24
 25 void buildx(int o, int l, int r) {
 26     if (l == r) {
 27         tx[o].mx = fis[l][0];
 28         tx[o].tag = 0;
 29         return;
 30     }
 31     int m = l + r >> 1;
 32     buildx(o << 1, l, m);
 33     buildx(o << 1 | 1, m + 1, r);
 34     tx[o].mx = max(tx[o << 1].mx, tx[o << 1 | 1].mx);
 35     tx[o].tag = 0;
 36 }
 37
 38 void buildy(int o, int l, int r) {
 39     if (l == r) {
 40         ty[o].mx = fis[l][1];
 41         ty[o].tag = 0;
 42         return;
 43     }
 44     int m = l + r >> 1;
 45     buildy(o << 1, l, m);
 46     buildy(o << 1 | 1, m + 1, r);
 47     ty[o].mx = max(ty[o << 1].mx, ty[o << 1 | 1].mx);
 48     ty[o].tag = 0;
 49 }
 50
 51 void pushdownx(int o) {
 52     if (!tx[o].tag) return;
 53     tx[o << 1].tag += tx[o].tag;
 54     tx[o << 1 | 1].tag += tx[o].tag;
 55     tx[o].mx += tx[o].tag;
 56     tx[o].tag = 0;
 57 }
 58
 59 void pushdowny(int o) {
 60     if (!ty[o].tag) return;
 61     ty[o << 1].tag += ty[o].tag;
 62     ty[o << 1 | 1].tag += ty[o].tag;
 63     ty[o].mx += ty[o].tag;
 64     ty[o].tag = 0;
 65 }
 66
 67 int queryx(int o, int l, int r) {
 68     if (l == r) return l;
 69     int m = l + r >> 1;
 70     pushdownx(o << 1);
 71     pushdownx(o << 1 | 1);
 72     if (tx[o << 1].mx > tx[o << 1 | 1].mx) return queryx(o << 1, l, m);
 73     return queryx(o << 1 | 1, m + 1, r);
 74 }
 75
 76 int queryy(int o, int l, int r) {
 77     if (l == r) return l;
 78     int m = l + r >> 1;
 79     pushdowny(o << 1);
 80     pushdowny(o << 1 | 1);
 81     if (ty[o << 1].mx > ty[o << 1 | 1].mx) return queryy(o << 1, l, m);
 82     return queryy(o << 1 | 1, m + 1, r);
 83 }
 84
 85 void changex(int o, int l, int r, int p, int v) {
 86     pushdownx(o);
 87     if (l == r) {
 88         tx[o].mx = v;
 89         return;
 90     }
 91     int m = l + r >> 1;
 92     if (p <= m) changex(o << 1, l, m, p, v);
 93     else changex(o << 1 | 1, m + 1, r, p, v);
 94     tx[o].mx = max(tx[o << 1].mx, tx[o << 1 | 1].mx);
 95 }
 96
 97 void changey(int o, int l, int r, int p, int v) {
 98     pushdowny(o);
 99     if (l == r) {
100         ty[o].mx = v;
101         return;
102     }
103     int m = l + r >> 1;
104     if (p <= m) changey(o << 1, l, m, p, v);
105     else changey(o << 1 | 1, m + 1, r, p, v);
106     ty[o].mx = max(ty[o << 1].mx, ty[o << 1 | 1].mx);
107 }
108
109 void updatax(int o, int l, int r) {
110     tx[o].mx = max(tx[o << 1].mx + tx[o << 1].tag, tx[o << 1 | 1].mx + tx[o << 1 | 1].tag);
111 }
112
113 void modifyx(int o, int l, int r, int x, int y, int d) {
114     if (x <= l && r <= y) {
115         tx[o].tag += d;
116         return;
117     }
118     pushdownx(o);
119     int m = l + r >> 1;
120     if (x <= m) modifyx(o << 1, l, m, x, y, d);
121     if (y > m) modifyx(o << 1 | 1, m + 1, r, x, y, d);
122     updatax(o, l, r);
123 }
124
125 void updatay(int o, int l, int r) {
126     ty[o].mx = max(ty[o << 1].mx + ty[o << 1].tag, ty[o << 1 | 1].mx + ty[o << 1 | 1].tag);
127 }
128
129 void modifyy(int o, int l, int r, int x, int y, int d) {
130     if (x <= l && r <= y) {
131         ty[o].tag += d;
132         return;
133     }
134     pushdowny(o);
135     int m = l + r >> 1;
136     if (x <= m) modifyy(o << 1, l, m, x, y, d);
137     if (y > m) modifyy(o << 1 | 1, m + 1, r, x, y, d);
138     updatay(o, l, r);
139 }
140
141 int work(int x, int y, int z) {
142     buildx(1, 1, n);
143     buildy(1, 1, n);
144     memset(sum, 0, sizeof sum);
145     for (int i = 1; i <= n; i ++) add(i, 1);
146     for (int i = 1; i <= m; i ++) {
147         while (tx[1].mx > x) {
148             int p = queryx(1, 1, n);
149             changex(1, 1, n, p, -inf);
150             if (Sum(p) - Sum(p - 1)) add(p, -1);
151         }
152         while (ty[1].mx > y) {
153             int p = queryy(1, 1, n);
154             changey(1, 1, n, p, -inf);
155             if (Sum(p) - Sum(p - 1)) add(p, -1);
156         }
157         if (q[i].s == 1) modifyx(1, 1, n, q[i].l, q[i].r, q[i].d);
158         if (q[i].s == 2) modifyy(1, 1, n, q[i].l, q[i].r, q[i].d);
159         if (q[i].s == 3) ans[i] += z * (Sum(q[i].r) - Sum(q[i].l - 1));
160     }
161 }
162
163 int main() {
164     scanf("%d", &T);
165     while (T --) {
166         scanf("%d", &n);
167         scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
168         for (int i = 1; i <= n; i ++) scanf("%d %d", &fis[i][0], &fis[i][1]);
169         scanf("%d", &m);
170         for (int i = 1; i <= m; i ++) {
171             scanf("%d %d %d", &q[i].s, &q[i].l, &q[i].r);
172             if (q[i].s != 3) scanf("%d", &q[i].d);
173         }
174         memset(ans, 0, sizeof ans);
175         work(x2, y2, 1), work(x1 - 1, y1 - 1, 1), work(x2, y1 - 1, -1), work(x1 - 1, y2, -1);
176         for (int i = 1; i <= m; i ++) if (q[i].s == 3)    printf("%d\n", ans[i]);
177     }
178     return 0;
179 }

HDU #5283 Senior's Fish

时间: 2024-10-06 15:11:29

HDU #5283 Senior's Fish的相关文章

hdu 5280 Senior&#39;s Array

题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5280 Senior's Array Description One day, Xuejiejie gets an array $A$. Among all non-empty intervals of $A$, she wants to find the most beautiful one. She defines the beauty as the sum of the interval. Th

hdu 5281 Senior&#39;s Gun

题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5281 Senior's Gun Description Xuejiejie is a beautiful and charming sharpshooter. She often carries $n$ guns, and every gun has an attack power $a[i]$. One day, Xuejiejie goes outside and comes across $m

hdu 5280 Senior&#39;s Array(最大子段和)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5280 题意:将一个长度为n的数组,将里面某一个数改为p,使改变后最大子段和最大. 题解:dp[i]=max(dp[i-1)+a[i],a[i]),表示以第 i 个数结束的最大子段和,时间复杂度为O(n). 1)由于n<=1000,可以暴力解决,将每一个数都依次改为p,求出最大的子段和,再去这些最大子段和中最大的,时间复杂度为O(n*n); #include <iostream> #inclu

HDU 5280 Senior&#39;s Array (暴力,水)

题意:给一个数列,再给一个数字p,要求p一定要替换掉数列中的一个元素,然后求最大连续子序列之和. 思路:1000*1000的复杂度,O(n*n) .就是每个都试,然后求和. 1 #include <bits/stdc++.h> 2 #define LL long long 3 #define pii pair<int,int> 4 #define INF 0x7f7f7f7f 5 using namespace std; 6 const int N=2000; 7 int a[N]

[最大子序列和]Hdu 5280 Senior&#39;s Array

题意:一个序列,在其中一个数必须替换成给定数字p的条件下,求最大连续子序列之和. 依次把每一个数替换成p,求每次的最大连续和,找出最大值.O(n^2). #include <cstdio> #include <iostream> #include <cstring> #include <algorithm> typedef long long ll; using namespace std; const int MAXN=1000+5; const int

HDU 5281 Senior&amp;#39;s Gun 杀怪

题意:给出n把枪和m个怪.每把枪有一个攻击力,每一个怪有一个防御力.假设某把枪的攻击力不小于某个怪的防御力则能将怪秒杀,否则无法杀死.一把枪最多仅仅能杀一个怪,不能用多把枪杀同一个怪.每杀一次怪能够得到枪的攻击力减去怪的防御力的的分数. 求得分的最大值. 贪心.首先我们考虑这样一种情况:用攻击力为A的枪杀防御力为a的怪,攻击力为B的枪杀防御力为b的怪.则得分为A - a + B - b. 最好还是设A ≤ B,则有a ≤ A ≤ B.b ≤ B.假设有A < b,那么我们考虑用B杀a.而不使用A

HDU 5280 Senior&#39;s Array 最大区间和

题意:给定n个数,要求必须将其中某个数改为P,求改动后最大的区间和可以为多少. 水题.枚举每个区间,如果该区间不修改(即修改该区间以外的数),则就为该区间和,若该区间要修改,因为必须修改,所以肯定是把最小的数修改为P能保证该区间最后和最大,所以比较两种方案的较大者.对于每个区间取出的较大者,再取总共的最大者即可.注意一个trick,枚举到整个区间的时候,是必须要修改一个数的,所以这个最大的这个区间只有一种方案.先预处理1~i的区间和,维护每个区间的最小值和区间和. #include <iostr

HDU 5281 Senior&#39;s Gun 杀怪

题意:给出n把枪和m个怪.每把枪有一个攻击力,每个怪有一个防御力.如果某把枪的攻击力不小于某个怪的防御力则能将怪秒杀,否则无法杀死.一把枪最多只能杀一个怪,不能用多把枪杀同一个怪.每杀一次怪可以得到枪的攻击力减去怪的防御力的的分数.求得分的最大值. 贪心.首先我们考虑这样一种情况:用攻击力为A的枪杀防御力为a的怪,攻击力为B的枪杀防御力为b的怪.则得分为A - a + B - b. 不妨设A ≤ B,则有a ≤ A ≤ B,b ≤ B.如果有A < b,那么我们考虑用B杀a,而不使用A枪也不杀b

HDU 5280 Senior&amp;#39;s Array 最大区间和

题意:给定n个数.要求必须将当中某个数改为P,求修改后最大的区间和能够为多少. 水题.枚举每一个区间.假设该区间不改动(即改动该区间以外的数),则就为该区间和,若该区间要改动,由于必须改动,所以肯定是把最小的数改动为P能保证该区间最后和最大,所以比較两种方案的较大者.对于每一个区间取出的较大者,再取总共的最大者就可以.注意一个trick,枚举到整个区间的时候,是必需要改动一个数的.所以这个最大的这个区间仅仅有一种方案. 先预处理1~i的区间和,维护每一个区间的最小值和区间和. #include