【ByteDance冬令营】DAY 4 总结 2019.2.19

迟更了,但还是要补的

contest
B

求积分,在这里插入图片描述
1e5组询问,s >= 1.0001
大胆的猜想,暴力计算前几项的求和,后面积分。看算多少项够。s很小的时候可以打表
考场上还是应该大胆尝试一下,想一小会看下有没有思路,这个做法也不浪费时间!!

C

求区间不同回文串个数。
注意不是本质不同

**manacher之后转化成
在这里插入图片描述
对于一个部分,比如说前面的和式,降序枚举左端点,把每个点的贡献函数看成两个部分,在拐点处修改。剩下的对于一个右端点来说是求前缀和,树状数组维护即可。
这种只会在一边出现拐点的,就枚举这个端点,另一个端点的贡献可以用数据结构方便的维护。如果枚举右端点就需要区间加等差数列,非常麻烦
把三个取min的式子拆成两个独立的分别统计,是很好的思路!
考场上以为可以直接差分贡献,把l,r分开统计,但是这样会算重,比如算l的时候统计到不在r区间范围内的。
必须要确认清楚算法,没有想清楚不能侥幸可以通过。特别是计数问题。这不是猜结论!

查错的时候当确认代码没有问题了,必须静心检验算法。
只要WA了,一定有错,静心检查!
一开始就应该完全想清楚算法,不能因为是赛场上时间紧张就浮躁的想要写题。没有想清楚任何时候都是莽撞、浪费时间的!通常想清楚之后,写代码的时间也缩短很多!

#include<bits/stdc++.h>
#define rep(i,l,r) for(register int i = l ; i <= r ; i++)
#define repd(i,r,l) for(register int i = r ; i >= l ; i--)
#define rvc(i,S) for(register int i = 0 ; i < (int)S.size() ; i++)
#define rvcd(i,S) for(register int i = ((int)S.size()) - 1 ; i >= 0 ; i--)
#define fore(i,x)for (register int i = head[x] ; i ; i = e[i].next)
#define forup(i,l,r) for (register int i = l ; i <= r ; i += lowbit(i))
#define fordown(i,id) for (register int i = id ; i ; i -= lowbit(i))
#define pb push_back
#define prev prev_
#define stack stack_
#define mp make_pair
#define fi first
#define se second
#define lowbit(x) (x&(-x))
using namespace std;

typedef long long ll;

const int maxn = 6e5 + 10;

struct node{
	int p,id;
};
vector <node> vec1[maxn],vec2[maxn];
ll ans[maxn];
vector <int> del[maxn];
char a[maxn],s[maxn];
int n,m,f[maxn];

void manacher(){
	rep(i,1,n) s[i << 1] = a[i] , s[i * 2 + 1] = '#';
	n = n * 2 + 2,  s[0] = '$' , s[1] = '#' , s[n] = '@';
	int r,p,i;
	for (r = p = 0 , f[1] = 1, i =2 ; i <= n ; i++){
		for ( f[i] = r > i ? min(r - i,f[p * 2 - i]) : 1 ; s[i - f[i]] == s[i + f[i]] ; f[i]++);
		if ( i + f[i] > r ) r = i + f[i] , p = i;
	}
}
int cnt[maxn];
ll sum[maxn];

inline void modify_sum(int id,int d){
	forup(i,id,n) sum[i] += d;
}
inline void modify_cnt(int id,int d){
	forup(i,id,n) cnt[i] += d;
}
inline ll query_sum(int id){
	ll res = 0;
	fordown(i,id) res += sum[i];
	return res;
}
inline ll query_cnt(int id){
	ll res = 0;
	fordown(i,id) res += cnt[i];
	return res;
}
void getans1(){
	rep(i,1,n) cnt[i] = 0 , sum[i] = 0;
	repd(i,n,1){
		modify_sum(i,i + 1);
		modify_cnt(i,1);
		del[i - f[i] + 1].pb(i);
		rvc(j,del[i]){
			int id = del[i][j];
			modify_sum(id,-(id + 1) + f[id]);
			modify_cnt(id,-1);
		}
		rvc(j,vec1[i]){
			node cur = vec1[i][j];
			ll res = query_sum(cur.p) - query_cnt(cur.p) * i;
			ans[cur.id] += res;
		}
	}
}
void getans2(){
	rep(i,1,n) cnt[i] = 0 , sum[i] = 0 , del[i].clear();
	rep(i,1,n){
		modify_sum(i,-i + 1);
		modify_cnt(i,1);
		del[i + f[i] - 1].pb(i);
		rvc(j,del[i]){
			int id = del[i][j];
			modify_sum(id,(id - 1) + f[id]);
			modify_cnt(id,-1);
		}
		rvc(j,vec2[i]){
			node cur = vec2[i][j];
			ll res = query_sum(i) - query_sum(cur.p - 1) + (query_cnt(i) - query_cnt(cur.p - 1)) * i;
			ans[cur.id] += res;
		}
	}
}
int main(){
	scanf("%s",a + 1) , n = strlen(a + 1);
	scanf("%d",&m);
	rep(i,1,m){
		int l,r;
		scanf("%d %d",&l,&r);
		ans[i] -= r - l + 2;
		l = 2 * l - 1, r = 2 * r + 1;
		int mid = (l + r) >> 1;
		vec1[l].pb((node){mid,i});
		vec2[r].pb((node){mid + 1,i});
	}	
	manacher();
	getans1();
	getans2();
	rep(i,1,m) printf("%lld\n",ans[i] / 2);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值