Codeforces Round #612 (Div. 1+Div. 2)

A

Find the longest continuous \ (P \) segment except the beginning .

#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<bitset>
#include<math.h>
#include<stack>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
typedef vector<int> vi;
typedef pair<int,int> pii;
const int N=100000;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define go(u,i) for (register int i=head[u],v=sq[i].to;i;i=sq[i].nxt,v=sq[i].to)
#define fir first
#define sec second
#define mkp make_pair
#define pb push_back
#define maxd 998244353
#define eps 1e-8
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    return x*f;
}

int n;
char s[100100];


int main()
{
	int T=read();
	while (T--)
	{
		n=read();
		scanf("%s",s+1);s[++n]='A';
		int ans=0,lst=0;
		rep(i,1,n)
		{
			if (s[i]=='A')
			{
				if (lst) ans=max(ans,i-lst-1);
				lst=i;
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}

B

Enumerate the first two strings, and the third string is determined, just use map to check.
(It seems a bit uncommon to write like this)

#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<bitset>
#include<math.h>
#include<stack>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
typedef vector<int> vi;
typedef pair<int,int> pii;
const int N=100000;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define go(u,i) for (register int i=head[u],v=sq[i].to;i;i=sq[i].nxt,v=sq[i].to)
#define fir first
#define sec second
#define mkp make_pair
#define pb push_back
#define maxd 998244353
#define eps 1e-8
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    return x*f;
}

int n,m,num[500],sum=0;
string s[2020];
map<string,int> mp;

bool diff(string a,string b)
{
	rep(i,0,m-1)
		if (a[i]==b[i]) return 0;
	return 1;
}

int main()
{
	n=read();m=read();
	sum='S'+'E'+'T';
	rep(i,1,n) {cin >> s[i];mp[s[i]]++;}
	int ans=0;
	rep(i,1,n)
	{
		rep(j,i+1,n)
		{
			string a="";
			rep(k,0,m-1)
			{
				if (s[i][k]==s[j][k]) a=a+s[i][k];
				else a+=(sum-s[i][k]-s[j][k]);
			}
			if (mp.count(a)) ans+=mp[a];
		}
	}
	cout << ans/3;
	return 0;
}

C

After 10,000 years of greed, I finally found out that dp was done.

Note \ (f_ {i, j, 0/1} \) representing the forward \ (I \) number used in \ (J \) odd, the \ (I \) is the maximum complexity when even / odd. Just transfer directly.

#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<bitset>
#include<math.h>
#include<stack>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
typedef vector<int> vi;
typedef pair<int,int> pii;
const int N=100000;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define go(u,i) for (register int i=head[u],v=sq[i].to;i;i=sq[i].nxt,v=sq[i].to)
#define fir first
#define sec second
#define mkp make_pair
#define pb push_back
#define maxd 998244353
#define eps 1e-8
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    return x*f;
}

namespace My_Math{
	#define N 100000

	int fac[N+100],invfac[N+100];

	int add(int x,int y) {return x+y>=maxd?x+y-maxd:x+y;}
	int dec(int x,int y) {return x<y?x-y+maxd:x-y;}
	int mul(int x,int y) {return 1ll*x*y%maxd;}
	ll qpow(ll x,int y)
	{
		ll ans=1;
		while (y)
		{
			if (y&1) ans=mul(ans,x);
			x=mul(x,x);y>>=1;
		}
		return ans;
	}
	int getinv(int x) {return qpow(x,maxd-2);}

	int C(int n,int m)
	{
		if ((n<m) || (n<0) || (m<0)) return 0;
		return mul(mul(fac[n],invfac[m]),invfac[n-m]);
	}

	void math_init()
	{
		fac[0]=invfac[0]=1;
		rep(i,1,N) fac[i]=mul(fac[i-1],i);
		invfac[N]=getinv(fac[N]);
		per(i,N-1,1) invfac[i]=mul(invfac[i+1],i+1);
	}
	#undef N
}
using namespace My_Math;

int n,a[110],f[110][110][2];

int main()
{
	n=read();
	rep(i,1,n) a[i]=read();
	memset(f,0x3f,sizeof(f));
	f[0][0][0]=f[0][0][1]=0;
	rep(i,1,n) rep(j,0,i)
	{
		if ((j) && ((a[i]&1) || (!a[i])))
		{
			f[i][j][1]=min(f[i][j][1],min(f[i-1][j-1][0]+1,f[i-1][j-1][1]));
		}
		if ((!(a[i]&1)) || (!a[i]))
		{
			f[i][j][0]=min(f[i][j][0],min(f[i-1][j][0],f[i-1][j][1]+1));
		}
	}
	int ans=min(f[n][(n+1)>>1][0],f[n][(n+1)>>1][1]);
	printf("%d",ans);
	return 0;
}

D

The case of no solution is more obvious: when the number of points in the subtree \ (i \) \ (<c_i \) has no solution.

Next, through the construction, it is pointed out that there is a construction method of the arrangement with the value of \ ([1, n] \) .

dfs the whole tree, find the unused \ ([_ 1 + 1)) number in the \ ([1, n] \) of the current point \ (u \) and assign it to the point \ (u \ ) . Then traverse its subtree. Before so we can keep (c_u \) \ number just assigned to \ (u \) sub-tree ratio (u \) \ number of small points.

#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<bitset>
#include<math.h>
#include<stack>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
typedef vector<int> vi;
typedef pair<int,int> pii;
const int N=100000;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define go(u,i) for (register int i=head[u],v=sq[i].to;i;i=sq[i].nxt,v=sq[i].to)
#define fir first
#define sec second
#define mkp make_pair
#define pb push_back
#define maxd 998244353
#define eps 1e-8
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    return x*f;
}

namespace My_Math{
	#define N 100000

	int fac[N+100],invfac[N+100];

	int add(int x,int y) {return x+y>=maxd?x+y-maxd:x+y;}
	int dec(int x,int y) {return x<y?x-y+maxd:x-y;}
	int mul(int x,int y) {return 1ll*x*y%maxd;}
	ll qpow(ll x,int y)
	{
		ll ans=1;
		while (y)
		{
			if (y&1) ans=mul(ans,x);
			x=mul(x,x);y>>=1;
		}
		return ans;
	}
	int getinv(int x) {return qpow(x,maxd-2);}

	int C(int n,int m)
	{
		if ((n<m) || (n<0) || (m<0)) return 0;
		return mul(mul(fac[n],invfac[m]),invfac[n-m]);
	}

	void math_init()
	{
		fac[0]=invfac[0]=1;
		rep(i,1,N) fac[i]=mul(fac[i-1],i);
		invfac[N]=getinv(fac[N]);
		per(i,N-1,1) invfac[i]=mul(invfac[i+1],i+1);
	}
	#undef N
}
using namespace My_Math;

struct node{int to,nxt;}sq[4040];
int all=0,head[2020];
int siz[2020],n,a[2020],ans[2020];
bool vis[2020];

void addedge(int u,int v)
{
	all++;sq[all].to=v;sq[all].nxt=head[u];head[u]=all;
}

void dfs(int u)
{
	int cnt=0;
	rep(i,1,n)
	{
		if (vis[i]) continue;
		if (cnt==a[u])
		{
			vis[i]=1;ans[u]=i;break;
		}
		else cnt++;
	}
	siz[u]=1;
	go(u,i)
	{
		dfs(v);siz[u]+=siz[v];
	}
	if (a[u]>siz[u]-1) {puts("NO");exit(0);}
}

int main()
{
	n=read();int rt;
	rep(i,1,n)
	{
		int fa=read();a[i]=read();
		if (!fa) rt=i;
		else addedge(fa,i);
	}
	dfs(rt);
	puts("YES");
	rep(i,1,n) printf("%d ",ans[i]);
	return 0;
}

E1&E2

Consider E1 first: Ask about \ ([1, n] \) and \ ([1, n-1] \) , where the extra strings from \ ([1, n] \) are \ ([i, n] \) (It ’s just that the characters in each string are shuffled), according to the difference between \ ([i, n] \) and \ ([i + 1, n] \) , you can deduce the first \ (i \ ) What is the character, and then get the entire string.

Consider E2 again: modeled on E1 we can get \ ([1, \ lfloor n / 2 \ rfloor] \) , and then ask again \ ([1, n] \) . The next idea is more clever: remember \ (f_ {i, x} \) is the number of occurrences of the character \ (x \) in all substrings of length \ (i \) , then \ (f_ {i + 1, x} -f_ {i, x} \) It is the number of occurrences of the character \ (x \) in \ ([i + 1, ni] \) (hand drawing is that the position of a prefix and a suffix cannot be increased, and the remaining positions can appear once more), inverted Push to get the second half.

The code is only for E2, E1 is included in it.

#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<bitset>
#include<math.h>
#include<stack>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
typedef vector<int> vi;
typedef pair<int,int> pii;
const int N=100000;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define go(u,i) for (register int i=head[u],v=sq[i].to;i;i=sq[i].nxt,v=sq[i].to)
#define fir first
#define sec second
#define mkp make_pair
#define pb push_back
#define maxd 998244353
#define eps 1e-8
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    return x*f;
}

bool cmp(string a,string b) {return (int)a.size()>(int)b.size();}

int n,ans[110],cnt[30],f[110][26];
multiset<string> word;
string s,str[110];

void ask(int l,int r)
{
	printf("? %d %d\n",l,r);fflush(stdout);
}

void answer()
{
	printf("! ");
	rep(i,1,n) putchar(ans[i]+'a');fflush(stdout);
}

void solve1(int n)
{
	if (n==1)
	{
		ask(1,1);
		cin >> s;ans[1]=s[0]-'a';
		return;
	}
	ask(1,n);
	rep(i,1,n*(n+1)/2)
	{
		cin >> s;
		sort(s.begin(),s.end());
		word.insert(s);
	}
	multiset<string>::iterator it;
	ask(1,n-1);
	rep(i,1,n*(n-1)/2)
	{
		cin >> s;
		sort(s.begin(),s.end());
		it=word.find(s);
		word.erase(it);
	}
	it=word.begin();
	rep(i,1,n) 
	{
		str[i]=*it;it++;
	}
	sort(str+1,str+1+n,cmp);
	multiset<string>::iterator pre,now;
	pre=word.begin();now=pre;now++;
	rep(i,1,n-1)
	{
		string s1=str[i],s2=str[i+1];
		int len=s1.size();
		rep(i,0,25) cnt[i]=0;
		rep(i,0,len-1) cnt[s1[i]-'a']++;
		rep(i,0,len-2) cnt[s2[i]-'a']--;
		rep(i,0,25)
		{
			if (cnt[i])
			{
				ans[n-len+1]=i;break;
			}
		}
		pre=now;
	}
	ans[n]=str[n][0]-'a';
}

void solve2()
{
	ask(1,n);
	rep(i,1,(n+1)*n/2)
	{
		cin >> s;
		int len=s.size();
		rep(j,0,len-1) f[len][s[j]-'a']++;
	}
	per(i,(n-1)>>1,0)
	{
		int l=i+1,r=n-i;
		rep(j,0,25) cnt[j]=0;
		rep(j,l,r-1) cnt[ans[j]]++;
		rep(j,0,25)
			if (f[i+1][j]-f[i][j]>cnt[j]) {ans[r]=j;break;}
	}
}

int main()
{
	n=read();
	if (n==1)
	{
		ask(1,1);
		cin >> s;
		printf("! ");cout << s;fflush(stdout);
		return 0;
	}
	solve1(n/2);
	solve2();
	answer();
	return 0;
}

F

The first possible collision is only the two adjacent points, otherwise there must be a point "crossing" another point in the process and another collision occurs.

So we can save all the possible collision events as the first collision, and then sort them according to time, and consider the probability of each event as the answer multiplied by one.

The probability of occurrence of the \ (i \) collision after chronological order = the probability of the first \ (i-1 \) collision not occurring-the probability of the previous \ (i \) collision not occurring. Find the probability that the first \ (i \) does not occur can be solved by dp, and remember that \ (f_ {i, 0/1} \) represents the probability that the \ (i \) point goes to the left / right. Since some collisions cannot occur, some positions cannot be transferred.

The single dp is \ (O (n) \) , if optimized, dp can be written in the form of a matrix, and then maintained with a line segment tree. \ (f_ {i, 0 / 1,0 / 1} \) representing the current interval \ ([l, r] \ ) in, \ (L \) and \ (R & lt \) probabilities when the respective directions. Then record whether the two states in the adjacent position are legal.

#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<bitset>
#include<math.h>
#include<stack>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
typedef vector<int> vi;
typedef pair<int,int> pii;
const int N=100000+100;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define go(u,i) for (register int i=head[u],v=sq[i].to;i;i=sq[i].nxt,v=sq[i].to)
#define fir first
#define sec second
#define mkp make_pair
#define pb push_back
#define maxd 998244353
#define eps 1e-8
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    return x*f;
}

namespace My_Math{
	#define N 100000

	int fac[N+100],invfac[N+100];

	int add(int x,int y) {return x+y>=maxd?x+y-maxd:x+y;}
	int dec(int x,int y) {return x<y?x-y+maxd:x-y;}
	int mul(int x,int y) {return 1ll*x*y%maxd;}
	ll qpow(ll x,int y)
	{
		ll ans=1;
		while (y)
		{
			if (y&1) ans=mul(ans,x);
			x=mul(x,x);y>>=1;
		}
		return ans;
	}
	int getinv(int x) {return qpow(x,maxd-2);}

	int C(int n,int m)
	{
		if ((n<m) || (n<0) || (m<0)) return 0;
		return mul(mul(fac[n],invfac[m]),invfac[n-m]);
	}

	void math_init()
	{
		fac[0]=invfac[0]=1;
		rep(i,1,N) fac[i]=mul(fac[i-1],i);
		invfac[N]=getinv(fac[N]);
		per(i,N-1,1) invfac[i]=mul(invfac[i+1],i+1);
	}
	#undef N
}
using namespace My_Math;

int n,x[N],v[N],tot=0,ban[N][2][2],p[N][2];
struct enode{int dis,v,op,id;}eve[N<<2];
bool operator <(enode p,enode q) {return 1ll*p.dis*q.v<1ll*q.dis*p.v;}

struct Matrix{
	int x[2][2];
	void init() {x[0][0]=x[1][0]=x[0][1]=x[1][1]=0;}
};

namespace Segment_Tree{
	Matrix seg[N<<2];
	
	Matrix pushup(Matrix a,Matrix b,int p)
	{
		Matrix c;c.init();
		rep(i,0,1) rep(j,0,1) 
		{
			c.x[i][j]=0;
			rep(p1,0,1) rep(p2,0,1)
				if (!ban[p][p1][p2])
					c.x[i][j]=add(c.x[i][j],mul(a.x[i][p1],b.x[p2][j]));
		}
		return c;
	}
	
	void build(int id,int l,int r)
	{
		if (l==r) 
		{
			seg[id].x[0][0]=p[l][0];
			seg[id].x[1][1]=p[l][1];
			return;
		}
		int mid=(l+r)>>1;
		build(id<<1,l,mid);build(id<<1|1,mid+1,r);
		seg[id]=pushup(seg[id<<1],seg[id<<1|1],mid);
	}
	
	void modify(int id,int l,int r,int pos)
	{
		if (l==r) return;
		int mid=(l+r)>>1;
		if (pos<=mid) modify(id<<1,l,mid,pos);
		else modify(id<<1|1,mid+1,r,pos);
		seg[id]=pushup(seg[id<<1],seg[id<<1|1],mid);
	}
}
using namespace Segment_Tree;

int main()
{
	n=read();
	int inv100=getinv(100);
	rep(i,1,n)
	{
		x[i]=read();v[i]=read();
		int np=read();
		p[i][1]=mul(np,inv100);p[i][0]=dec(1,p[i][1]);
	}
	//rep(i,1,n) cout << p[i][0] << " " << p[i][1] << endl;
	rep(i,1,n-1)
	{
		eve[++tot]=(enode){x[i+1]-x[i],v[i+1]+v[i],1,i};
		if (v[i+1]>v[i]) eve[++tot]=(enode){x[i+1]-x[i],v[i+1]-v[i],2,i};
		if (v[i]>v[i+1]) eve[++tot]=(enode){x[i+1]-x[i],v[i]-v[i+1],3,i};
	}
	sort(eve+1,eve+1+tot);
	//rep(i,1,tot) printf("%d %d %d %d\n",eve[i].dis,eve[i].v,eve[i].id,eve[i].op);
	build(1,1,n);
	int ans=0,lstp=1;
	rep(i,1,tot)
	{
		int id=eve[i].id,op=eve[i].op;
		if (op==1) ban[id][1][0]=1;
		else if (op==2) ban[id][0][0]=1;
		else if (op==3) ban[id][1][1]=1;
		modify(1,1,n,id);
		int nowp=0,tim=mul(eve[i].dis,getinv(eve[i].v));
		//cout << tim << endl;
		rep(j,0,1) rep(k,0,1) nowp=add(nowp,seg[1].x[j][k]);
		int p=dec(lstp,nowp);
		ans=add(ans,mul(p,tim));
		lstp=nowp;
	}
	printf("%d",ans);
	return 0;
}

G

Consider the change of the answer when adding a character \ (S_i \) , it is not difficult to find that the contribution is the current string \ (\ rm {border} \) .

Considering the increase in the section \ (I \) when the characters \ (\ rm {border} \ ) changes the set of \ (\ rm {border} \ ) elements of a set \ (X \) , if the \ (of S_ {x + 1} \ neq S_i \) Then \ (x \) will be removed from the collection; if \ (S_1 = S_i \) , then \ (1 \) will be added to \ (\ rm {border} \) In the collection.

In fact, it is easy to know the elements in the current \ (\ rm {border} \) set, which is the \ (nxt [i-1], nxt [nxt [i-1]], \ cdots, \) set in kmp The addition of elements is very easy to maintain. For the deletion operation, the position of the first next character other than \ (S_i \) is maintained for the current \ (\ rm {border} \) collection , and then the violence will go up and delete the contribution, The weights deleted each time can be directly maintained with the line segment tree. Since there will only be \ (O (n) \) insertions, there is no problem with brute force deletion.

Next, we must consider \ (w_i \) , which means that all current weights need to be taken from \ ( w_i \) \ (\ min \) , we can use \ (\ mathrm {map} \) to maintain the current answer The number of occurrences of each weight, and then each time the violence is found to be larger than \ (w_i \) and modified, because each newly added value will only be involved in one \ (\ min \) operation at most, so it is complicated The degree is also correct.

Note that the final answer may burst long long, so you need to write an int128.

The code is a bit ugly

#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<bitset>
#include<math.h>
#include<stack>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef pair<int,int> pii;
const int N=600000+100;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define go(u,i) for (register int i=head[u],v=sq[i].to;i;i=sq[i].nxt,v=sq[i].to)
#define fir first
#define sec second
#define mkp make_pair
#define pb push_back
#define maxd 998244353
#define eps 1e-8
#define mask (1<<30)-1
const ll bas=1e18;
map<int,int> mp;
int n,jmp[N],nxt[N],str[N];
char s[N];
map<int,int>::iterator it,it2;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    return x*f;
}
 
namespace My_Math{
	#define N 100000
 
	int fac[N+100],invfac[N+100];
 
	int add(int x,int y) {return x+y>=maxd?x+y-maxd:x+y;}
	int dec(int x,int y) {return x<y?x-y+maxd:x-y;}
	int mul(int x,int y) {return 1ll*x*y%maxd;}
	ll qpow(ll x,int y)
	{
		ll ans=1;
		while (y)
		{
			if (y&1) ans=mul(ans,x);
			x=mul(x,x);y>>=1;
		}
		return ans;
	}
	int getinv(int x) {return qpow(x,maxd-2);}
 
	int C(int n,int m)
	{
		if ((n<m) || (n<0) || (m<0)) return 0;
		return mul(mul(fac[n],invfac[m]),invfac[n-m]);
	}
 
	void math_init()
	{
		fac[0]=invfac[0]=1;
		rep(i,1,N) fac[i]=mul(fac[i-1],i);
		invfac[N]=getinv(fac[N]);
		per(i,N-1,1) invfac[i]=mul(invfac[i+1],i+1);
	}
	#undef N
}
using namespace My_Math;
 
namespace Segment_Tree{
	
	int seg[N<<2];
	
	void modify(int id,int l,int r,int p,int v)
	{
		if (l==r) {seg[id]=v;return;}
		int mid=(l+r)>>1;
		if (p<=mid) modify(id<<1,l,mid,p,v);
		else modify(id<<1|1,mid+1,r,p,v);
		seg[id]=min(seg[id<<1],seg[id<<1|1]);
	}
	
	int query(int id,int l,int r,int ql,int qr)
	{
		if ((l>=ql) && (r<=qr)) return seg[id];
		int mid=(l+r)>>1,ans=2e9;
		if (ql<=mid) ans=min(ans,query(id<<1,l,mid,ql,qr));
		if (qr>mid) ans=min(ans,query(id<<1|1,mid+1,r,ql,qr));
		return ans;
	}
}
using namespace Segment_Tree;
 
pair<ull,ull> ans;
 
void addans(ull val)
{
	ans.fir+=val;
	if (ans.fir>=bas) 
	{
		ans.fir-=bas;ans.sec++;
	}
}
 
void out()
{
	if (ans.sec)
		printf("%llu%018llu\n",ans.sec,ans.fir);
	else printf("%llu\n",ans.fir);
}
 
int main()
{
	n=read();
	ull nans=0,ansc=0,answ=0;
	scanf("%s",s);int w=read();
	mp[w]++;nans+=w;ansc=w%26;answ=w;
	addans(nans);out();
	memset(str,-1,sizeof(str));
	modify(1,1,n,1,w);str[1]=s[0]-'a';
	int j=0;
	rep(i,2,n)
	{
		scanf("%s",s);w=read();
		int ch=(ansc+s[0]-'a')%26;
		w^=(answ&mask);str[i]=ch;
		modify(1,1,n,i,w);
		while ((j) && (str[j+1]!=str[i])) j=nxt[j];
		if (str[j+1]==str[i]) j++;nxt[i]=j;
		if (str[i]==str[1])
		{
			nans+=w;mp[w]++;
		}
		if (str[nxt[i-1]+1]!=str[i]) jmp[i-1]=nxt[i-1];
		else jmp[i-1]=jmp[nxt[i-1]];
		int k=nxt[i-1];
		while (k)
		{
			if (str[k+1]!=str[i])
			{
				int val=query(1,1,n,i-k,i-1);
				mp[val]--;nans-=val;
				k=nxt[k];
			}
			else k=jmp[k];
		}
		for (it=mp.upper_bound(w);it!=mp.end();)
		{
			mp[w]+=it->sec;
			nans-=1ull*(it->fir-w)*it->sec;
			it->sec=0;it2=it;it++;
			mp.erase(it2);
		}
		addans(nans);
		ansc=(ansc+nans)%26;
		answ=(answ+nans)&mask;
		out();
	}
	return 0;
}

Guess you like

Origin www.cnblogs.com/encodetalker/p/12723549.html