D. Tokitsukaze and Meeting
题意:
给定一个01字符串s,代表着一群学生。接下来他们会按顺序进入的矩阵,新进入的会留在
,已经进入的推后。
问第 i 个学生进入后,矩阵的有多少行含1,有多少列含1。
做法:
表示第
个学生进入后,矩阵有多少行含1。
很明显,可以由
转移而来,再判定以
结尾的这一段长为
的区间是否含1即可。
对于列,手画一下矩阵,发现总是只有那一列在变化,其他的都没有改变过,所以直接开一个数组简单维护一下即可。
char s[N];
int f[N], sum[N], c[N];
void solve()
{
int n, m;
cin >> n >> m;
scanf("%s", s + 1);
for (int i = 1; i <= n * m; i++) sum[i] = sum[i - 1] + s[i] - '0';
for (int i = 1; i <= n * m; i++)
{
if (i >= m) f[i] = f[i - m];
f[i] += (sum[i] - sum[max(i - m, 0ll)] > 0);
}
int now = 1;
int S = 0;
for (int i = 1; i <= n * m; i++)
{
if (c[now] == 0 && s[i] == '1')
{
S++;
c[now] = 1;
}
printf("%lld ", S + f[i]);
now++;
if (now == m + 1) now = 1;
}
for (int i = 1; i <= m; i++) c[i] = 0;
for (int i = 1; i <= n*m; i++) f[i] = sum[i] = 0;
puts("");
}
Tokitsukaze and Strange Inequality
题意:
找这样的四元组,他们的下标一次递增,且
。
做法:
数据才5000,完全可以的找出
这样的逆序对,然后在他们的区间里统计答案。
有的数会被统计很多次,所以可以确定了的时候,倒着遍历确定
,这样就知道了哪些数会被统计多少次。
int a[N], c[N];
int n;
void add(int i, int x)
{
while(i <= n)
{
c[i] += x;
i += (i & -i);
}
}
int que(int i)
{
int ret = 0;
while(i)
{
ret += c[i];
i -= (i & -i);
}
return ret;
}
void solve()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
scanf("%lld", &a[i]);
}
int ans = 0;
for (int i = 1; i <= n; i++)
{
int cnt = 0;
for (int j = n; j > i; j--)
{
ans += que(a[j]) * cnt;
if (a[i] > a[j])
{
cnt++;
}
}
add(a[i], 1);
}
cout << ans << "\n";
for (int i = 1; i <= n; i++) c[i] = 0;
}