A. Short Program
每一位是独立的,分别考虑每一位初始是
B. Teams Formation
首先把同一辆车中的相邻
若
若
第一种是相邻两辆车之间被消掉的人数
第二种则反之。考虑什么时候会出现这种情况,发现一定有
但还有一种特殊的情况,即上述的第二种情况中,所有正中间元素恰好被消完了(
细节虽然多,但讨论清楚就好了。
C. Tournament
考虑建图,若运动员
考虑加入一个运动员
#include <cstdio>
#include <cstring>
#include <set>
using namespace std;
const int MAXN=55000;
const int MAXK=10;
int n, k, X, Y;
struct Node
{
int v[2][MAXK], siz;
bool operator < (const Node& rhs) const
{
return v[X][Y]<rhs.v[X][Y];
}
void insert(const Node& rhs)
{
for (int i=0; i<k; i++)
{
v[0][i]=min(v[0][i], rhs.v[0][i]);
v[1][i]=max(v[1][i], rhs.v[1][i]);
}
siz+=rhs.siz;
}
};
int main()
{
// freopen("C.in", "r", stdin);
// freopen("C.out", "w", stdout);
scanf("%d%d", &n, &k);
set<Node> s;
for (int i=1; i<=n; i++)
{
Node t; t.siz=1;
for (int j=0; j<k; j++)
{
int x; scanf("%d", &x);
t.v[0][j]=t.v[1][j]=x;
}
Node a, b;
memset(a.v, 0, sizeof a.v);
memset(b.v, 0x3f, sizeof b.v);
for (int j=0; j<k; j++)
{
X=0, Y=j; auto it=s.lower_bound(t);
if (it!=s.begin()) a=max(a, *(--it));
X=1, Y=j; it=s.upper_bound(t);
if (it!=s.end()) b=min(b, *it);
}
if (a<b) s.insert(t);
else
{
auto lt=s.find(b), rt=s.find(a); rt++;
while (lt!=rt) t.insert(*lt), s.erase(lt++);
s.insert(t);
}
printf("%d\n", s.rbegin()->siz);
}
return 0;
}
D. Magic Breeding
从答案入手考虑。容易观察到每个生物的某个特定的性状只会从初始的
然而仅这样做并不能优化复杂度,但是会有一个性质:不同两位之间的运算是独立的。对于每一位,我们可以得到初始生物在这一位上的值,若对于两个不同的性状,初始生物在这一位上的值两两相同,则后续的操作也会得到同样的结果。我们一共有
实现时需要预处理每种性状对应的初始值,可以用 std::bitset 加速维护过程。复杂度为
#include <cstdio>
#include <bitset>
#include <algorithm>
using namespace std;
const int MAXN=110000;
const int MAXK=15;
const int MAXS=1<<12;
int a[MAXN][MAXK];
int c[MAXN][MAXK];
bitset<MAXS> b[MAXN];
int main()
{
// freopen("D.in", "r", stdin);
// freopen("D.out", "w", stdout);
int n, k, q;
scanf("%d%d%d", &n, &k, &q);
for (int j=1; j<=k; j++)
for (int i=1; i<=n; i++)
scanf("%d", &a[i][j]);
for (int i=1; i<=n; i++)
for (int j=1; j<=k; j++)
for (int p=1; p<=k; p++)
if (a[i][p]>=a[i][j]) c[i][j]|=1<<p-1;
for (int i=1; i<=k; i++)
for (int j=0; j<MAXS; j++) b[i][j]=j>>i-1&1;
for (int i=1, m=k; i<=q; i++)
{
int t, x, y;
scanf("%d%d%d", &t, &x, &y);
switch (t)
{
case 1: b[++m]=b[x]|b[y]; break;
case 2: b[++m]=b[x]&b[y]; break;
case 3:
int ans=0;
for (int j=1; j<=k; j++)
if (b[x][c[y][j]]) ans=max(ans, a[y][j]);
printf("%d\n", ans);
break;
}
}
return 0;
}