在十一国庆期间,我们给祖国过生日,祖国妈妈可高兴了,让gg特意为我们准备了一场模拟!

 

其实这一次的模拟不算太毒瘤,部分分还是可以拿到的,不过考完调正解的时候调到崩溃……

 

T1 matrix

  这道题起手就是30。

  然后我憋了一会儿:这题有一个特别的地方,就是所有询问都在修改之后,那也就应当把所有修改做完,然后快速的询问。

  于是想到了一个类似扫描线的做法,把修改排序,然后维护一棵线段树,区间修改,单点查询,复杂度是O(nqlogn),只能60,结果考试的时候我还算成了O(qlogn),以为能AC……

  正解其实比扫描线简单多了:二维差分!这就是为什么n, m <= 2000了:一是能O(n2),二是能开的下二维数组。于是对于一个矩形的修改(xa, ya)到(xb, yb),我们模仿一维差分,dif[xa][ya]++; dif[xa][yb + 1]--; dif[xb + 1][ya]--; dif[xb + 1][yb + 1]++ 即可(dif是差分数组)。

  最后跑一遍二维前缀和,得到了修改后的矩阵,于是询问的时候就是O(1)的二维前缀和了。

60分代码(线段树区间修改可以改成差分,达到O(nq),然鹅还是60)

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cmath>
  4 #include<algorithm>
  5 #include<cstring>
  6 #include<cstdlib>
  7 #include<cctype>
  8 #include<vector>
  9 #include<stack>
 10 #include<queue>
 11 using namespace std;
 12 #define enter puts("") 
 13 #define space putchar(' ')
 14 #define Mem(a, x) memset(a, x, sizeof(a))
 15 #define rg register
 16 typedef long long ll;
 17 typedef double db;
 18 const int INF = 0x3f3f3f3f;
 19 const db eps = 1e-8;
 20 const int maxn = 2e3 + 5;
 21 inline ll read()
 22 {
 23     ll ans = 0;
 24     char ch = getchar(), last = ' ';
 25     while(!isdigit(ch)) {last = ch; ch = getchar();}
 26     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
 27     if(last == '-') ans = -ans;
 28     return ans;
 29 }
 30 inline void write(ll x)
 31 {
 32     if(x < 0) x = -x, putchar('-');
 33     if(x >= 10) write(x / 10);
 34     putchar(x % 10 + '0');
 35 }
 36 
 37 int n, m, p, q;
 38 
 39 int a[maxn][maxn];
 40 ll Sum[maxn][maxn];
 41 
 42 int l[maxn << 2], r[maxn << 2], lzy[maxn << 2], sum[maxn << 2];
 43 void build(const int& L, const int& R, const int& now)
 44 {
 45     l[now] = L; r[now] = R;
 46     if(L == R) return;
 47     int mid = (L + R) >> 1;
 48     build(L, mid, now << 1);
 49     build(mid + 1, R, now << 1 | 1);
 50 }
 51 void pushdown(const int& now)
 52 {
 53     if(lzy[now])
 54     {
 55         sum[now << 1] += (r[now << 1] - l[now << 1] + 1) * lzy[now];
 56         sum[now << 1 | 1] += (r[now << 1 | 1] - l[now << 1 | 1] + 1) * lzy[now];
 57         lzy[now << 1] += lzy[now];
 58         lzy[now << 1 | 1] += lzy[now];
 59         lzy[now] = 0;
 60     }
 61 }
 62 void update(const int& L, const int& R, const int& now, const int& flg)
 63 {
 64     if(L == l[now] && R == r[now])
 65     {
 66         sum[now] += (R - L + 1) * flg;
 67         lzy[now] += flg; return;
 68     }
 69     pushdown(now);
 70     int mid = (l[now] + r[now]) >> 1;
 71     if(R <= mid) update(L, R, now << 1, flg);
 72     else if(L > mid) update(L, R, now << 1 | 1, flg);
 73     else update(L, mid, now << 1, flg), update(mid + 1, R, now << 1 | 1, flg);
 74     sum[now] = sum[now << 1] + sum[now << 1 | 1];
 75 }
 76 int query(const int& idx, const int& now)
 77 {
 78     if(sum[now] == 0) return 0;
 79     if(l[now] == r[now]) return sum[now];
 80     pushdown(now);
 81     int mid = (l[now] + r[now]) >> 1;
 82     if(idx <= mid) return query(idx, now << 1);
 83     else return query(idx, now << 1 | 1);
 84 }
 85 
 86 struct Node1
 87 {
 88     int L, R, flg;
 89 };
 90 vector<Node1> v1[maxn];
 91 
 92 int main()
 93 {
 94     freopen("matrix.in", "r", stdin);
 95     freopen("matrix.out", "w", stdout);
 96     n = read(); m = read(); p = read(); q = read();
 97     build(1, n, 1);
 98     for(rg int i = 1; i <= p; ++i)
 99     {
100         int xa = read(), ya = read(), xb = read(), yb = read();
101         v1[ya].push_back((Node1){xa, xb, 1}); v1[yb + 1].push_back((Node1){xa, xb, -1});
102     }
103     for(rg int i = 1; i <= m; ++i)
104     {
105         for(rg int j = 0; j < (int)v1[i].size(); ++j)
106             update(v1[i][j].L, v1[i][j].R, 1, v1[i][j].flg);
107         for(rg int j = 1; j <= n; ++j) a[j][i] = query(j, 1);
108     }
109     for(rg int i = 1; i <= n; ++i)
110         for(rg int j = 1; j <= m; ++j) 
111             Sum[i][j] = Sum[i][j - 1] + Sum[i - 1][j] - Sum[i - 1][j - 1] + a[i][j];
112     for(rg int i = 1; i <= q; ++i)
113     {
114         int xa = read(), ya = read(), xb = read(), yb = read();
115         write(Sum[xb][yb] - Sum[xb][ya - 1] - Sum[xa - 1][yb] + Sum[xa - 1][ya - 1]);
116         enter;    
117     }
118     return 0;
119 }
View Code

相关文章: