拍照
树状数组。求出静止状态下,每个点能看到多少个向右开的船c1[i],多少个向左开的船c2[i]。
max{c1[i], max{ c2[j], (i <= j) } }即为答案。
注意要离散化,否则会Tle。
1 #include <bits/stdc++.h> 2 typedef long long ll; 3 using namespace std; 4 5 const int maxn =2e4; 6 //c1 向右开的船 7 int c1[maxn<<2], c2[maxn<<2]; 8 int s1[maxn<<2], s2[maxn<<2]; 9 10 int lowbit(int x){ return x&-x;} 11 void add(int x, int d, int* c){//c[x]++; 12 while(x <= (maxn<<2)){ 13 c[x] += d; 14 x += lowbit(x); 15 } 16 } 17 void Add(int l, int r, int* c){ 18 add(l, 1, c); 19 add(r+1, -1, c); 20 } 21 int sum(int x, int* c){ 22 int ret = 0; 23 while(x > 0){ 24 ret += c[x]; 25 x -= (x&-x); 26 } 27 return ret; 28 } 29 30 int n; 31 int ope[maxn], tot; 32 struct p{ 33 int l, r, d; 34 p(){} 35 p(int l, int r, int d):l(l), r(r), d(d){} 36 }; 37 p pp[maxn]; 38 39 int main(){ 40 int t, ca = 1;scanf("%d", &t); 41 while(t--){ 42 scanf("%d", &n); 43 memset(c1, 0, sizeof(c1)); 44 memset(c2, 0, sizeof(c2)); 45 int l, r, x, y, z, d; 46 47 tot = 0; 48 for(int i = 0; i < n; i++){ 49 scanf("%d%d%d%d", &x, &y, &z, &d); 50 l = y-z+maxn, r = x+z+maxn; 51 ope[tot++] = l, ope[tot++] = r; 52 pp[i] = p(l, r, d); 53 } 54 55 sort(ope, ope+tot); 56 //tot = unique(ope, ope+tot)-ope; 57 for(int i = 0; i < n; i++){ 58 int l = lower_bound(ope, ope+tot, pp[i].l)-ope+1; 59 int r = lower_bound(ope, ope+tot, pp[i].r)-ope+1; 60 int d = pp[i].d; 61 if(l <= r) 62 Add(l, r, (d == 1? c1 : c2)); 63 } 64 65 for(int i = 0; i < (maxn<<2); i++) 66 s1[i] = sum(i, c1); 67 for(int i = 0; i < (maxn<<2); i++) 68 s2[i] = sum(i, c2); 69 70 int ans = 0; 71 for(int i = (maxn<<2)-2; i > 0; i--){ 72 s2[i] = max(s2[i], s2[i+1]); 73 ans = max(ans, s1[i]+s2[i]); 74 } 75 printf("Case #%d:\n%d\n", ca++, ans); 76 } 77 return 0; 78 }
时间: 2024-11-10 01:11:23