T1:这一题有很多种方法都能过。
设f[j]表示选数的集合为j的构成两条相等的边选的是集合为j的数(f[j]=0/1),这个可以用3^n的暴力来求。
求出了f之后,我们考虑如果存在j和k,使f[j]=f[k]=1且j&k=0,那么我们就可以用j集合里的数的和/2*k集合里的数的和/2来更新答案。这个我们可以通过枚举j,然后枚举与j没有交集的k来做。
T2:我们发现食人鱼的运动周期最多是12,那么我们可以列出dp方程,然后用矩阵乘法来转移。
T3:这一题看似平衡树,其实用线段树就可以了。
发现所操作都不影响珠子之间的顺序,也就是说项链的编号一定是顺时针1~n或逆时针1~n的。那么我们就设A表示原1号位置现在的位置,B(B=1/-1)表示现在项链的顺序是顺时针还是逆时针。
然后我们就用线段树来维护区间答案。线段树要维护三个值,分别是区间答案、区间左端点颜色,区间右端点颜色。
对于R k操作,我们直接把A+k就行了。
对于F操作,就是B*=(-1),同时A要转到对称的位置。
对于S操作,我们就直接在线段树上单点查询和修改。
P操作就是区间修改。
C和CS就是区间查询。
细节较多,有一些就不讲了。下面贴一下怎样查找现在某个位置上对应的原项链的编号的代码:
int get(int x)
{
int y;
if(B==1)y=x-A+1;
if(B==-1)y=A+n-x+1;
y=y%n;
if(y<0)y+=n;
if(y==0)y=n;
return y;
}