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

 

posted @ 2021-09-29 20:43  HZOI_LYM  阅读(49)  评论(0编辑  收藏  举报