蒟蒻的心路历程
上来看B,结果不会。。。
回来做A,写完之后nantf已经切B了。
回来做B,花了13min磕了出来。
继续做C,自闭。
继续做D,花了10min磕了出来。
继续做E,一开始有点自闭,后来口胡了出来,但是实现略微死人,花了1h磕了出来。
继续自闭。。。。。。。
A XORinacci
(a,b,aoplus b,a,b,aoplus b,ldots)
B Uniqueless
使用two-pointer, 前缀和优化后判断(O(n)),时间复杂度(O(n^2))
D Restore Permutation
从后往前确定,目前求(p_i),已知({p_1,p_2,ldots,p_i})和(s_i),可以通过线段树上二分得到(p_i),之后把(p_i)从线段树中删去。时间复杂度(O(nlog n))。
E Let them Slide
对于一个数列(a[1,l]),设其中的最大值为(a[p]),则在([p,p+w-l])这段区间的贡献为(a[p]),在([1,p-1])这段区间中(i)的贡献为(maxlimits_{jin [max(1,i-w+l),i]}a_j),([p+w-l+1,w])这段区间中(i)的贡献为(maxlimits_{jin [i,min(w,i+w-l)]}a_j),特别要考虑是否能不经过一个点(i),还有(a[p]<0)的情况也需要特殊考虑中间这段([p,p+w-l])(其他的贡献为0)。这个取(max)的运算可以使用单调队列计算。
由于([p,p+w-l])这段区间非常大,所以可以打一个全局tag,表示所有数加上多少。
然后加一堆判断并注意正负号就可以过了。
#include<bits/stdc++.h>
#define Rint register int
using namespace std;
typedef long long LL;
const int N = 1000003;
int n, w, l, a[N], p, q[N], front, rear;
LL all, ans[N];
int main(){
scanf("%d%d", &n, &w);
for(Rint i = 1;i <= n;i ++){
scanf("%d", &l); p = 1;
for(Rint j = 1;j <= l;j ++){
scanf("%d", a + j);
if(a[j] > a[p]) p = j;
}
if(a[p] < 0){
if(w >= 2 * l) continue;
int tmp = w - l; front = rear = 0;
for(Rint i = 1;i <= tmp;i ++){
while(front < rear && a[q[rear - 1]] <= a[i]) -- rear;
q[rear ++] = i;
}
for(Rint i = tmp + 1;i <= l;i ++){
while(front < rear && q[front] < i - tmp) ++ front;
while(front < rear && a[q[rear - 1]] <= a[i]) -- rear;
q[rear ++] = i;
ans[i] -= a[q[front]];
}
continue;
}
all += a[p];
int tmp = w - l; front = rear = 0;
for(Rint i = 1;i <= p - 1;i ++){
while(front < rear && q[front] < i - tmp) ++ front;
while(front < rear && a[q[rear - 1]] <= a[i]) -- rear;
q[rear ++] = i;
if(i <= tmp) ans[i] += min(a[p], a[p] - a[q[front]]);
else ans[i] += a[p] - a[q[front]];
}
front = rear = 0;
for(Rint i = w;i > p + tmp;i --){
while(front < rear && q[front] > i) ++ front;
while(front < rear && a[q[rear - 1]] <= a[i - tmp]) -- rear;
q[rear ++] = i - tmp;
if(i > l) ans[i] += min(a[p], a[p] - a[q[front]]);
else ans[i] += a[p] - a[q[front]];
}
}
for(Rint i = 1;i <= w;i ++)
printf("%I64d ", all - ans[i]);
}
C Magic Grid
将所有数按照(x>>4)分类,填进(frac{n}{4} imes frac{n}{4})的矩阵中,一类的(16)个数填进一个方格,每个方格是样例1的矩阵。这样在(8|n)的时候每行每列为0,否则每行每列为13.
F Bits And Pieces
首先固定(a_i),然后从高位到低位试答案,这一位可以填1当且仅当(a_i)的这一位为1或者是当前答案(x)的超集在(a_i)右边至少有两个数。
考虑预处理出(x)的超集的最靠右的两个下标。这个可以用FMT做,具体就是对每个([0,2^{21}))的数维护一个pair,维护值为(x)的最靠右的两个下标。然后把FMT的加法改成合并pair运算(将一个pair的两个数加进另一个pair)就可以了。之后上面的条件就可以轻松判断了。
时间复杂度(O((n+m)log m))
G Polygons
首先我们知道,肯定要固定一个点,所有的正多边形都要用这个点。
其次,如果填了一个正(x)边形,那么(x)的所有约数的正多边形也要填入。且相对于(x)的所有的约数(不含(x))的正多边形,正(x)边形要多用(varphi(x))个点。所以考虑按照([1,n])的所有(varphi)值排序,然后取最小的(k)个,同时我们知道(d|x)则(varphi(d)le varphi(x)),所以满足这个条件。
注意判掉正1边形和正2边形。时间复杂度(O(nlog n))。
H Red Blue Tree
此题过 ♂ 难,只会膜倒数2min切掉这题的tourist.