NOIP模拟65
T1:
首先比较直接的暴力思路显然为统计每个初始联通块的大小
再k^2枚举子矩形,考虑优化,比较套路的优化方式:考虑变量
发现再矩形移动过程中仅有两列发生变化,于是再每一行枚举时
可以先暴力处理出初始矩形,再将变化的两列暴力处理即可
处理联通块大小可以通过并查集或vector实现,需要注意
子矩形内部存在联通块的情况,可以通过二维前缀和容斥实现
代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define I int 4 #define C char 5 #define B bool 6 #define V void 7 #define D double 8 #define LL long long 9 #define UI unsigned int 10 #define UL unsigned long long 11 #define P pair<I,I> 12 #define MP make_pair 13 #define a first 14 #define b second 15 #define debug cout << "It's Ok Here !" << endl; 16 #define lowbit(x) (x & -x) 17 #define FP(x) freopen (#x,"r",stdin) 18 #define FC(x) freopen (#x,"w",stdout) 19 const I N = 505; 20 I n,len,idx,A[N][N],pre[N][N],buc[N*N],ans; 21 B jud[N*N]; 22 C s[N]; 23 queue <I> q; 24 inline I read () { 25 I x(0),y(1); C z(getchar()); 26 while (!isdigit(z)) { if (z == '-') y = -1; z = getchar(); } 27 while ( isdigit(z)) x = x * 10 + (z ^ 48), z = getchar(); 28 return x * y; 29 } 30 inline V Max (I &a,I b) { a = a > b ? a : b; } 31 inline V Min (I &a,I b) { a = a < b ? a : b; } 32 inline I max (I a,I b) { return a > b ? a : b; } 33 inline I min (I a,I b) { return a < b ? a : b; } 34 inline V swap (I &a,I &b) { a ^= b, b ^= a, a ^= b; } 35 inline I abs (I a) { return a >= 0 ? a : -a; } 36 inline P operator + (const P &a,const P &b) { 37 return MP (a.a + b.a,a.b + b.b); 38 } 39 inline P operator - (const P &a,const P &b) { 40 return MP (a.a - b.a,a.b - b.b); 41 } 42 struct DJS { 43 I f[N*N],size[N*N]; 44 I get (I x) { return x == f[x] ? x : f[x] = get (f[x]); } 45 inline V merge (I x,I y) { 46 I fx (get (x)), fy (get (y)); 47 if(fx == fy) return ; f[fy] = fx, size[fx] += size[fy]; 48 } 49 }DJS; 50 inline I Divide (I i,I j) { 51 I tmp (0); 52 for (I k(0);k < len; ++ k) { 53 I fa; 54 for (I l(0);l < len; ++ l) { 55 fa = DJS.get (A[i + k][j + l]); 56 if (!buc[fa]) tmp += DJS.size[fa]; buc[fa] ++ ; 57 if (!jud[fa]) jud[fa] = 1, q.push (fa); 58 } 59 fa = DJS.get (A[i - 1][j + k]); 60 if (!buc[fa]) tmp += DJS.size[fa]; buc[fa] ++ ; 61 if (!jud[fa]) jud[fa] = 1, q.push (fa); 62 fa = DJS.get (A[i + len][j + k]); 63 if (!buc[fa]) tmp += DJS.size[fa]; buc[fa] ++ ; 64 if (!jud[fa]) jud[fa] = 1, q.push (fa); 65 fa = DJS.get (A[i + k][j + len]); 66 if (!buc[fa]) tmp += DJS.size[fa]; buc[fa] ++ ; 67 if (!jud[fa]) jud[fa] = 1, q.push (fa); 68 } 69 return tmp - pre[i + len - 1][j + len - 1] + pre[i - 1][j + len - 1] + pre[i + len - 1][j - 1] - pre[i - 1][j - 1]; 70 } 71 signed main () { 72 FP (grid.in), FC (grid.out); 73 n = read(), len = read(); 74 for (I i(1);i <= n; ++ i) { 75 scanf ("%s",s + 1); 76 for (I j(1);j <= n; ++ j) { 77 if (s[j] == '.') { 78 A[i][j] = ++idx, DJS.f[idx] = idx, DJS.size[idx] = 1; 79 if (A[i - 1][j]) DJS.merge (A[i - 1][j],A[i][j]); 80 if (A[i][j - 1]) DJS.merge (A[i][j - 1],A[i][j]); 81 } 82 pre[i][j] = pre[i - 1][j] + pre[i][j - 1] - pre[i - 1][j - 1] + (s[j] == '.'); 83 } 84 } 85 for (I i(1);i + len - 1 <= n; ++ i) { 86 I fa,tmp; 87 for (I j(1);j + len - 1 <= n; ++ j) { 88 if (j == 1) tmp = Divide (i,j); 89 else { 90 for (I k(0);k < len; ++ k) { 91 fa = DJS.get (A[i + k][j - 2]); 92 buc[fa] -- ; if (!buc[fa]) tmp -= DJS.size[fa]; 93 fa = DJS.get (A[i + k][j + len]); 94 if (!buc[fa]) tmp += DJS.size[fa]; buc[fa] ++ ; 95 if (!jud[fa]) jud[fa] = 1, q.push (fa); 96 if (A[i + k][j - 1]) tmp ++ ; if (A[i + k][j + len - 1]) tmp -- ; 97 } 98 fa = DJS.get (A[i - 1][j - 1]); 99 buc[fa] -- ; if (!buc[fa]) tmp -= DJS.size[fa]; 100 fa = DJS.get (A[i - 1][j + len - 1]); 101 if (!buc[fa]) tmp += DJS.size[fa]; buc[fa] ++ ; 102 if (!jud[fa]) jud[fa] = 1, q.push (fa); 103 fa = DJS.get (A[i + len][j - 1]); 104 buc[fa] -- ; if (!buc[fa]) tmp -= DJS.size[fa]; 105 fa = DJS.get (A[i + len][j + len - 1]); 106 if (!buc[fa]) tmp += DJS.size[fa]; buc[fa] ++ ; 107 if (!jud[fa]) jud[fa] = 1, q.push (fa); 108 } 109 Max (ans,tmp); 110 } 111 while (!q.empty ()) { I x (q.front ()); jud[x] = 0, buc[x] = 0; q.pop (); } 112 } 113 printf ("%d\n",ans + len * len); 114 }
T2:
首先n^2暴力比较好像,考虑每个位置的最长合法序列
dp转移方程为:f[i] = max (f[j] + 1) (j < i && a[j] < a[i] && i - j >= a[i] - a[j])
非常明显的三维偏序,直接采用CDQ分治解决:需要注意
分治边界的处理,树状数组的快速clear方式,第一维天然有序(i,j)
第二维通过sort解决(a[i],a[j]),第三维通过树状数组维护(i - a[i],j - a[j])
代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define I int 4 #define C char 5 #define B bool 6 #define V void 7 #define D double 8 #define LL long long 9 #define UI unsigned int 10 #define UL unsigned long long 11 #define P pair<I,I> 12 #define MP make_pair 13 #define a first 14 #define b second 15 #define debug cout << "It's Ok Here !" << endl; 16 #define lowbit(x) (x & -x) 17 #define FP(x) freopen (#x,"r",stdin) 18 #define FC(x) freopen (#x,"w",stdout) 19 const I N = 5e5 + 3; 20 I n,ans,f[N]; 21 P a[N]; 22 inline I read () { 23 I x(0),y(1); C z(getchar()); 24 while (!isdigit(z)) { if (z == '-') y = -1; z = getchar(); } 25 while ( isdigit(z)) x = x * 10 + (z ^ 48), z = getchar(); 26 return x * y; 27 } 28 inline V Max (I &a,I b) { a = a > b ? a : b; } 29 inline V Min (I &a,I b) { a = a < b ? a : b; } 30 inline I max (I a,I b) { return a > b ? a : b; } 31 inline I min (I a,I b) { return a < b ? a : b; } 32 inline V swap (I &a,I &b) { a ^= b, b ^= a, a ^= b; } 33 inline I abs (I a) { return a >= 0 ? a : -a; } 34 inline P operator + (const P &a,const P &b) { 35 return MP (a.a + b.a,a.b + b.b); 36 } 37 inline P operator - (const P &a,const P &b) { 38 return MP (a.a - b.a,a.b - b.b); 39 } 40 inline B com1 (const P &a,const P &b) { return a.b < b.b; } 41 inline B com2 (const P &a,const P &b) { 42 return a.a == b.a ? a.b - a.a > b.b - b.a : a.a < b.a; 43 } 44 struct BIT { 45 I c[N]; 46 inline V insert (I x,I y) { 47 for (;x <= n;x += lowbit(x)) 48 Max (c[x],y); 49 } 50 inline I preque (I x) { I ans(0); 51 for (; x ;x -= lowbit(x)) 52 Max (ans,c[x]); 53 return ans; 54 } 55 inline V clear (I x) { 56 for (;x <= n;x += lowbit (x)) 57 c[x] = 0; 58 } 59 }B1; 60 V CDQ (I l,I r) { 61 if (l == r) { 62 Max (f[a[l].b],a[l].a <= a[l].b); 63 return ; 64 } 65 I mid (l + r >> 1); 66 CDQ (l,mid); 67 sort (a + l,a + mid + 1,com2), sort (a + mid + 1,a + r + 1,com2); 68 I p1 (l), p2 (mid + 1); 69 while (p2 <= r) { 70 while (a[p1].a < a[p2].a && p1 <= mid) { 71 if (a[p1].b >= a[p1].a) B1.insert (a[p1].b - a[p1].a + 1,f[a[p1].b]); 72 p1 ++ ; 73 } 74 if (a[p2].b - a[p2].a < 0) goto flag; 75 Max (f[a[p2].b], B1.preque (a[p2].b - a[p2].a + 1) + 1); 76 flag : p2 ++ ; 77 } 78 for (I i(l);i <= mid; ++ i) if (a[i].b >= a[i].a) 79 B1.clear (a[i].b - a[i].a + 1); 80 sort (a + mid + 1,a + r + 1,com1); 81 CDQ (mid + 1,r); 82 } 83 signed main () { 84 FP (sequence.in), FC (sequence.out); 85 n = read(); 86 for (I i(1);i <= n; ++ i) 87 a[i].a = read(), a[i].b = i; 88 CDQ (1,n); 89 for (I i(1);i <= n; ++ i) 90 Max (ans,f[i]); 91 printf ("%d\n",ans); 92 }
考虑更优秀的做法,发现若满足后两个条件,那么第一个条件自然满足
于是并不需要CDQ解决,可以直接通过sort解决第二维再通过树状数组维护
第三维,省去了CDQ分治的log
代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define I int 4 #define C char 5 #define B bool 6 #define V void 7 #define D double 8 #define LL long long 9 #define UI unsigned int 10 #define UL unsigned long long 11 #define P pair<I,I> 12 #define MP make_pair 13 #define a first 14 #define b second 15 #define debug cout << "It's Ok Here !" << endl; 16 #define lowbit(x) (x & -x) 17 #define FP(x) freopen (#x,"r",stdin) 18 #define FC(x) freopen (#x,"w",stdout) 19 const I N = 5e5 + 3; 20 I n,ans; 21 P a[N]; 22 inline I read () { 23 I x(0),y(1); C z(getchar()); 24 while (!isdigit(z)) { if (z == '-') y = -1; z = getchar(); } 25 while ( isdigit(z)) x = x * 10 + (z ^ 48), z = getchar(); 26 return x * y; 27 } 28 inline V Max (I &a,I b) { a = a > b ? a : b; } 29 inline V Min (I &a,I b) { a = a < b ? a : b; } 30 inline I max (I a,I b) { return a > b ? a : b; } 31 inline I min (I a,I b) { return a < b ? a : b; } 32 inline V swap (I &a,I &b) { a ^= b, b ^= a, a ^= b; } 33 inline I abs (I a) { return a >= 0 ? a : -a; } 34 inline P operator + (const P &a,const P &b) { 35 return MP (a.a + b.a,a.b + b.b); 36 } 37 inline P operator - (const P &a,const P &b) { 38 return MP (a.a - b.a,a.b - b.b); 39 } 40 inline B com (const P &a,const P &b) { 41 return a.a == b.a ? a.b > b.b : a.a < b.a; 42 } 43 struct BIT { 44 I c[N]; 45 inline V insert (I x,I y) { 46 for (;x <= n;x += lowbit(x)) 47 Max (c[x],y); 48 } 49 inline I preque (I x) { I ans(0); 50 for (; x ;x -= lowbit(x)) 51 Max (ans,c[x]); 52 return ans; 53 } 54 }B1; 55 signed main () { 56 FP (sequence.in), FC (sequence.out); 57 n = read(); 58 for (I i(1);i <= n; ++ i) 59 a[i].a = read(), a[i].b = i - a[i].a; 60 sort (a + 1,a + n + 1,com); 61 for (I i(1);i <= n; ++ i) { 62 if (a[i].b < 0) continue; 63 I tmp (B1.preque (a[i].b + 1)); 64 B1.insert (a[i].b + 1,tmp + 1); 65 Max (ans,tmp + 1); 66 } 67 printf ("%d\n",ans); 68 }