P6974 [NEERC2015]Adjustment Office 题解
水思维题。
大意
有一个矩阵 $a$,$a_{ij}=i+j$。
两个操作,一个删一行,一个删一列。
删完之后剩下的行 / 列不会向上 / 左补齐。
每次操作后输出所有删掉的 $a_{ij}$ 的和。
思路
这种题一看就可以用各种神奇的数据结构来做,
然而我不会它是道橙题,没有必要。
我们分别分析操作 $1,2$ 对矩阵的影响。
操作1
设消的是第 $i$ 行。
对剩下的行:无影响。
对剩下的列:对于第 $j$ 列,使这一列的和减少 $i+j$。
操作2
设消的是第 $j$ 列。
对剩下的行:对于第 $i$ 行,使这一行的和减少 $i+j$。
对剩下的列:无影响。
接下来,我们就要处理询问的结果了。
行的和
易得第 $i$ 行初始和为 $\dfrac {n(n+1)}2+ni$。
此时设共消了 $x$ 列,消去的每一列的编号和为 $p$。
那么根据上面,这个初始和要减去 $xi+p$
列的和
易得第 $j$ 列初始和为 $\dfrac {n(n+1)}2+nj$。
此时设共消了 $y$ 行,消去的每一行的编号和为 $q$。
那么根据上面,这个初始和要减去 $yj+q$
这样,每次操作就是 $O(1)$ 的,总复杂度 $O(q)$。
代码
注意 long long
。
#include <iostream>
#define int long long
using namespace std;
int n, x, y, p, q, t;bool fr[1000050], fc[1000050];
signed main()
{
cin >> n >> t;
for(int i = 0;i < t;++i)
{
int m;char c;cin >> c >> m;
switch(c)
{
case 'R':
if(fr[m]) {cout << 0 << endl;break;}
fr[m] = 1;++y;q += m;cout << n * (n + 1) / 2 + n * m - (x * m + p) << endl;break;
case 'C':
if(fc[m]) {cout << 0 << endl;break;}
fc[m] = 1;++x;p += m;cout << n * (n + 1) / 2 + n * m - (y * m + q) << endl;break;
}
}
return 0;
}