居然没出原题听奇怪。
好难啊。
T1
计算几何。
把x有交集的墙合并起来。
然后再每一个墙的端点上加入每一个(x)轴以上的点和这个端点的向量。
然后每个(vector)极角排序即可。
查询的时候对每个端点算出和当前点的向量,然后在(vector)中查询比这个点小的个数。
如果当前端点是左端点就+个数个,否则答案-个数个。
相当于一种差分,而会作出贡献的自然是那些被墙挡住的部分。也就是大于和起点的向量小于和终点的向量。
T2
线段树扫描线。
首先将查询的询问分成([1,l-1]->[l,r])和([1,r]->[l,r])这两个。
然后考虑如何维护这样的前缀信息。
扫描线。
设当前扫描位置为(l),那么扫描线上位置(j)记录的信息就是([1,l]->j)的所有信息。
然后我们需要的扫描线是可以得到如下一个函数:
这个有点麻烦了。
因为需要代入一个(x)而算出众多贡献。
考虑如何做。
我们将(f)设为一个如下的函数:
然后首先初始化这个函数。
先直接算出(1->[1,n])的所有(mex),然后初始化(a_i=mex[i],b_i=0)。
这样初始的答案就是对的了。
然后考虑修改。
维护如下一个值(mx[x])表示线段树区间中(mex[i])的最大值。
然后我们发现(mex[x])是递增的。
我们需要修改的是一段连续的区间。
设(nxt[i])为(a[i])在(i)之后下一次出现的位置。
也就是说当前位置从(l)移动到(l+1)的时候,对于所有的(iin [l+1,nxt[l]-1]),以这些位置为终点的所有(mex)值均要和(a[l])取(min)。
因为这些部分(a[l])并没有出现。
这样我们改变(mx[x])的值。
同时也要改变(a,b)的值。
怎么做?
我们发现贡献对于后面代入的某个值是这样的。
如果某个位置将要被修改((mx[x]>a[l]))
那么对于这个位置来说,([1,l])的所有起点对于当前这个右端点的贡献全部都减去(mx[x]-a[l]),所以(b_x-=l*(mx[x]-a[l]))。
而同时,([l+1,i])也就是需要查询代入的值这一部分是不受影响的,所以(a_x+=mx[x]-a[l]),这样直接用标记下传即可。
然后修改掉(mx[x]=d)即可。
查询的时候查询区间的(k)和以及(b)和,让他们一同做出贡献。
仍然有一个问题。
就是我们暴力的修改复杂度是无法保证的。
因此我们维护这样一个值(s[x]=0/1),表示当前区间的所有点是否是同一个值,修改的时候如果是同一个值直接修改,否则向下递归。
然后一种颜色加入和被覆盖的复杂度都是(logn),那么总的复杂度仍然是:(O(nlogn))
T3
后缀排序。
考虑一种等价于最小表示法的方式。
如果当前位置为(i),那么(a[i])出现的上个位置为(j),那么(j)的贡献即为((i-j)*w^{j-l}),这样会得到一个(hash)值。
发现这种表示方法等价于最小表示法。
然后考虑后缀排序求出(height)数组,然后求出本质不同字串个数。
可以直接对后缀排序,然后比较的时候用二分+(hash)求(lcp),如上给出了一种(hash)的求法
可以用主席树进行维护。
主席树每个位置代表以当前点为右端点,主席树上的位置为左端点的后缀的前缀的(hash)值。
然后根据上面我说的方式进行(hash)的更新。
可以发现相当于在给主席树的一段前缀区间加上一个等比数列,这里由于所有的等比数列公比相同,所以直接求首项和即可标记永久化来维护这一点。
然后可以求(hash)了,直接二分+(hash)求出(lcp),然后比较下一个字符即可。
下一个字符可以用每种颜色的(vector)+(lower_bound)来求出。
然后就可以比较了。
比较的次数为(nlogn)次,每次比较的复杂度是(log^2n),所以总的复杂度是(O(nlog^3n))。
会被卡常,改成(stable\_sort),也就是归并排序(%%%湘源大神告诉我的)就可以过了。
另外(height)可以直接利用(lcp)来求。
这样就可以直接算出本质不同字串个数了。