1. 程式人生 > 其它 >NOIP模擬65

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 }
View Code

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 }
View Code

  考慮更優秀的做法,發現若滿足後兩個條件,那麼第一個條件自然滿足

於是並不需要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 }
View Code