Codeforces 587F

对所有子串建出AC自动机,并求出fail树。考虑对询问区间差分一下后从左到右扫描线处理,那么可以变为两种操作:对fail树上某个子树中所有点的权值 + 1 +1 +1,查询某个字符串对应的所有节点的权值和。
这里给出一个做法,我们可以将每个节点映射到二维平面上,两维坐标分别是fail树上的dfs序和所属字符串的编号,那么原问题就变为给横坐标在某个区间内的所有点 + 1 +1 +1和求出纵坐标 = = =某个数的所有点的权和。
这两个操作都容易用KD-Tree维护,时间复杂度 O ( ( ∣ S ∣ + q ) ∣ S ∣ \mathcal O((|S|+q)\sqrt{|S|} O((S+q)S 。这种做法常数比较大,跑得比按字符串长度分块慢很多。。。

#include <bits/stdc++.h>
#define end end2
#define inf 0x3f3f3f3f

using namespace std;

typedef long long ll;

struct Point {
   
  int x,y;
  Point() {
   }
  Point(int a,int b):x(a),y(b) {
   }
};

bool cmp1(Point x,Point y) {
   
  return x.x<y.x;
}

bool cmp2(Point x,Point y) {
   
  return x.y<y.y;
}

Point p[100005];

namespace KDT {
   

int ch[100005][2],size[100005],tot;
int minx[100005],maxx[100005];
int miny[100005],maxy[100005];

int addv[100005],num[100005];
ll sumv[100005];

inline void pushdown(int o) {
   
  if (addv[o]) {
   
  	int ls=ch[o][0],rs=ch[o][1];
  	num[o]+=addv[o];
  	if (ls) {
   
  		addv[ls]+=addv[o];
  		sumv[ls]+=(ll)addv[o]*size[ls];
	  }
	if (rs) {
   
		addv[rs]+
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值