On the subject of team explain Mo &

On the subject of team explain Mo &

First, the team thought Mo and Mo team of pre-knowledge

  Mo team is an offline algorithm to achieve his borrowed the idea of ​​block. Before learning Mo team, I suggest learning about the block, and it has a certain understanding.

Second, MO team

  Now an example is given: bzoj2038, firstly the questions asked can be transformed into a section, $ \ sum \ limits_ {i = 1} ^ {n} many [i] \ times (many [i] -1) $, $ many [i] $ $ I $ denotes the color interval $ [l, r] in the number of $.

  We first consider the violence, we were each asked for $ O (n) $ color statistics, barrels figured out with the number of each color, we use the $ O (n) $ sweep the whole barrel, the answer to that is obtained can.

  Now consider the knowledge we have to explain, for the Mo team, asked to have a necessary condition, all inquiries must be offline, because we want to be a sort of all inquiries. We maintain two pointers $ l, r $, two pointers indicate the current range we have statistics that in the interval $ [l, r] in all colors $ have been recorded in the bucket, and now consider two inquiry between maintenance, suppose we have now processed interrogation $ [a, b] $, now treated interrogation $ [c, d] $, $ l we pointer, R & lt $ violent beating in sequence, the pointer $ l from $ $ $ A to $ c $, R & lt pointer $ $ $ $ b from the $ d $, so we can use $ O ((| ca | + | db |) \ times modification time) to two $ Changing between the two inquiries.

  We consider the movement of the pointer, a total of four cases: $ l $ of the left, $ l $ is right, $ r $ the left, $ r $ the right. First consider the $ l $ is right, let's move the pointer, which will require the contribution of the color of $ l-1 $ subtracting this position, consider changing color $ l-1 $ position to answer contributions, from $ many [col [l-1]] ^ 2 $, become $ (many [col [l-1]] - 1) ^ 2 $, something about which the $ \ Delta $ enough, do not forget that last $ many [ col [l-1]] - $. Consider left $ r $ pointers, he and $ l $ pointer to the right is a reason, just the color of $ r + 1 $ position deleted. Consider $ l $ pointer to the left, the right is different is that this time is a plus, let's move the pointer, so we just want $ col [l] $ added to the contribution years, $ col [l] $ answers the contribution from $ many [col [l]] ^ 2 $, become a $ (many [col [l]] + 1) ^ 2 $, and finally do not forget to $ many [col [l]] ++ $. Consider $ r $ pointer to the right, and he left the $ l $ is a reason, just add a digital $ ++ r $ contribution into position.

  We now know that a range of information, you just need to want to know the other $ O (left + right end point from point distance) $. But we algorithm is not good enough, we will consider the agenda in front of the sort, we consider a very good sort of way that we best time complexity, we define a $ Siz $, so that it is equal to $ \ sqrt n $, we follow the $ Siz $ block, we first define the sort of keywords, asking where the number range of $ l $ blocks, second keyword, ask the size of the $ r $, so that we can get a very good time complexity, we analyze, because the $ l $ in the same block in the right end point for all inquiries are in ascending order of arrangement, so for $ l $ to all inquiries within a block of our $ r $ pointer will traverse up from $ 1 to $ $ n $, a total of $ \ sqrt n $ blocks, of a total of $ r $ pointer moves only $ O (n \ sqrt n) $ times. We now consider the $ l $ pointers, each of our inquiry will only move in where the block, so it is still $ O (n \ sqrt n) $, so the final time complexity is $ O (n \ sqrt n) $ .

#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std;
#define N 100010
int Siz,n,m,num[N],many[N],l,r;long long now,ans[N];
struct Ask {int l,r,id;}ask[N];
int back (int x) {return x / (x +%! = 0);
bool cmp(const Ask &a,const Ask &b)
	{return bel(a.l)<bel(b.l)||(bel(a.l)==bel(b.l)&&a.r<b.r);}
bool cmp2(const Ask &a,const Ask &b) {return a.id<b.id;}
void add(int x)
	{now-=1ll*many[x]*(many[x]-1),many[x]++,now+=1ll*many[x]*(many[x]-1);}
void del(int x)
	{now-=1ll*many[x]*(many[x]-1),many[x]--,now+=1ll*many[x]*(many[x]-1);}
int main ()
{
	scanf("%d%d",&n,&m),Siz=sqrt(n);
	for(int i=1;i<=n;i++) scanf("%d",&num[i]);
	for(int i=1;i<=m;i++) scanf("%d%d",&ask[i].l,&ask[i].r),ask[i].id=i;
	sort(ask+1,ask+m+1,cmp),l=1,r=0;
	for(int i=1;i<=m;i++)
	{
		while(l>ask[i].l) --l,add(num[l]);
		while(r<ask[i].r) ++r,add(num[r]);
		while(l<ask[i].l) del(num[l]),l++;
		while(r>ask[i].r) del(num[r]),r--;
		ans[ask[i].id]=now;
	}
	sort(ask+1,ask+m+1,cmp2);
	for(int i=1;i<=m;i++)
	{
		long long tmp=ask[i].r-ask[i].l+1;
		tmp*=(tmp-1);
		if(!ans[i]) printf("%d/%d\n",0,1);
		else printf("%lld/%lld\n",ans[i]/__gcd(ans[i],tmp),tmp/__gcd(tmp,ans[i]));
	}
}

Third, MO team

Little B's inquiry bzoj3781

  This question and ask the same basic example, we only need Mo teams algorithm maintains the number of intervals in each number that appears, and dynamic maintenance requirements and the title out just fine.

bzoj3585 mex

  This question is seeking the interval $ mex $, we consider the use of digital Mo team maintain each of a range of occurrences, of course, buckets, we can now consider what figures to contribute answers, that number is less than equal to the number of only $ n $ there will be contributions, so we only need to record less than or equal to $ n $ numbers. But we know the number of times each number appears, how to find $ mex $? We doors consider the block, we block numbers, we consider maintaining an array $ have [i] $, represents a number of the points of the first $ i $ blocks how many numbers appeared, this array is in Mozambique team when maintenance in the example, we will change the position of the answer to be assigned a function, in this function we use reasonable idea of ​​the block, we use $ sqrt n $ of time to determine \ $ \ sqrt n $ blocks are not all full, namely $ have [i] = Siz $, find the first is not full, $ \ sqrt n $ convenience and this block of time to find a no-show, the first number to the time complexity $ n \ sqrt n + m \ sqrt n $.

The two sister bzoj3809 Gty force job sequence && bzoj3236

  Thinking we on to consider a question, we are still in accordance with the weight block or each block statistics of a $ have [i] $, represents a number of the points of the first $ i $ blocks how many numbers appeared, consider seeking answer, block weight for the divided blocks directly coupled $ have [i] $, we scattered like violence, total time complexity is still $ n \ sqrt n + m \ sqrt n $ .

  This question of course we can also set the tree on an array of Mo team, for each digital emerging in Fenwick tree plus a corresponding position for the disappearance of a number, the corresponding position in Fenwick tree minus one, each is seeking a range and my writing this time overrun, the time complexity $ O (n \ sqrt n log_2 ^ n) $. Not so good.

bzoj3289 Mato file management

  We consider the nature of solving the problem, every time a given interval $ [l, r] $, seeking $ [l, r] $ all numbers in reverse order of the number of the composition. Mo is still considered the team, This question is not above problem is to use buckets to maintain the number of occurrences, we use Fenwick tree.

  Consider moving each time to add behind a number that is larger than this count will reverse its form a pair, with Fenwick tree check, plus. Each time in the last removal of a number larger than this count will reverse its form a pair, with Fenwick tree check, minus. Each time you add a number in front of most, smaller than this number will be associated with the decrease of the number of a reverse order, with Fenwick tree check, plus. Every removed before most a number, this number smaller than the number will decrease to a reverse its use Fenwick tree check, minus.

Third, the team with modifications MO

  Modified with Mo Mo team's ideas and the idea of ​​the same team, are sorted according to the idea of ​​partition, but with modifications Mo team will be more than a pointer to $ t $, indicates the time that the pointer indicates the current modifications to modify our where, for each modification, we defined four values: were modified, modify the contents of the former location, modification, the modified content. For each inquiry, we define a multi-value represents the last modification time in front of him.

  We will sort it changes, and then add a keyword in the original two keywords that time, when the judgment condition, when the left point range of two interrogation in a block, a block in the right spot, we will The two inquiries ordered by time. For our team the original Mo circulation to certain modifications, because we have a pointer called a time, we need to adjust the pointer in good time before the adjustment range two pointers, so that we can carry out the operation.

Example: bzoj2120 number of colors

  We consider the above explanation, we will copy down the color sequence, sequence meter copy was obtained as a $ change $, we do all modification operations on $ change $, so we can get four values ​​for each modification operation (Modify time, modify the location, content before the amendment, modified content). In this way we will be able to write in accordance with the above ideas.

  We found that if the $ Siz = \ sqrt n $ you will run very slowly, so we consider what we have to change the size of the $ Siz $, we consider the $ Siz $ becomes $ n ^ {\ frac {2} {3} } $, so we analyze the time complexity.

  For moving time, in the case where the left and right end of the same block, to the right of the monotone time, a total of $ O (n) $, where one of the left and right end blocks changed from time to move back up directly $ n $ $ 1 $ complexity $ O (n) $, where the left and right end blocks each $ O (n ^ \ frac {1} {3}) $ species, combined two by two with a $ O (n ^ \ frac {2} {3} ) $ species, each of which is $ O (n) $, overall complexity is $ O (n ^ \ frac {5} {3}) $.

  For the movement of the right end point, the endpoint is located at around the same block, each move a maximum of $ n ^ \ frac {2} {3} $, up to a total movement, n-complexity $ $ $ views right point is O ( n ^ \ frac {5} {3}) $, when the left block is the point where the change, the right end up moving from $ n-$ up to $ 1 $, the distance between $ n-$, up to $ n ^ \ frac {2} {3} $ times this movement, the complexity is $ O (n ^ \ frac {4} {3}) $; total right point moves complexity is $ O (n ^ \ frac {5} {3}) $.

  For the movement of the left end point, the left end point of the block unchanged, a moving distance up to $ O (n ^ \ frac {2} {3}) $, a total of $ O (n ^ \ frac {5} {3}) $ . While inter-block, since the block where the point is monotonic left moving to the right, the maximum complexity of each stride block is the rightmost run to the leftmost block is the previous block, from $ O ( n ^ \ frac {1} {3}) $, overall complexity $ O (n) $. So the left point moves total complexity is $ O (n ^ \ frac {5} {3}) $.

  Under normal circumstances, with the team will modify Mo Mo tree and tied the team title.

#include <cstdio>
#include <algorithm>
using namespace std;
#define N 1000010
You can define 330
int n,m,l,r,t,idx,cnt,many;
int not [N], num [N], bin [N], military [N];
struct Oper {int pla,num,old;}oper[N];
struct Ask {int l,r,tim,id;}ask[N];
ask_bel (int, int x) {return x / (x +%! = 0);
bool cmp(const Ask &a,const Ask &b)
{
	return (ask_bel(a.l)==ask_bel(b.l))?
	(ask_bel(a.r)==ask_bel(b.r)?a.tim<b.tim:a.r<b.r):a.l<b.l;
}
void add(int x) {++bin[x];if(bin[x]==1) many++;}
void del(int x) {--bin[x];if(bin[x]==0) many--;}
void change(int x,int y) {if(x<=r&&x>=l) add(y),del(num[x]);num[x]=y;}
int main ()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&num[i]),chan[i]=num[i];
	for(int i=1;i<=m;i++)
	{
		char kind[3];scanf("%s",kind);
		if(kind[0]=='Q') ++idx,scanf("%d%d",&ask[idx].l,&ask[idx].r)
			,ask[idx].tim=cnt,ask[idx].id=idx;
		else ++cnt,scanf("%d%d",&oper[cnt].pla,&oper[cnt].num),
			oper [cnt] = .old chan [oper [cnt] .pla] Chan [oper [cnt] .pla] = oper [cnt] .num;
	}
	sort(ask+1,ask+idx+1,cmp);
	for(int i=1;i<=idx;i++)
	{
		while(t<ask[i].tim) ++t,change(oper[t].pla,oper[t].num);
		while(t>ask[i].tim) change(oper[t].pla,oper[t].old),t--;
		while(l>ask[i].l) --l,add(num[l]);
		while(r<ask[i].r) ++r,add(num[r]);
		while(l<ask[i].l) del(num[l]),l++;
		while(r>ask[i].r) del(num[r]),r--;
		ans[ask[i].id]=many;
	}
	for(int i=1;i<=idx;i++) printf("%d\n",ans[i]);
}

Fourth, the tree Mo team

  Tree Mo team a total of two, one is seeking information subtree tree, another tree path information is required, both can be transferred from the tree into the sequence.

  We consider the first, we consider something called a $ dfs $ sequence, we can Praying tree information, transforming information for a range of $ dfs $ for the sake of order, directly on the Mo team on the sequence it.

  The second consideration, we consider a call push the stack order of things, so we can get a $ 2n $ length sequence. Now suppose we statistics interval $ [l, r] $, i.e. closed interval sandwiched two pointers. In this zone where, if two of the same number, that a number of push pop sequence in this statistical range, we think they are the two cancel each other out. As shown below:

  We observed the figure, we can find a problem, we will pass interrogation divided into two categories, one is two points ancestral relationships, that we have a direct interrogation interval other ancestral sequences to the pull stack another point order, remove the offset of this interval, it is just good is our path. Another point is that the two ancestral relationships is not, we ask the other section is a sequence showing a stack point, another point to the stack order, if not for the interval, i.e., $ r \ lt l $, we exchanged two point, we get this interval is not difficult to find out after the offset point, and the remaining point is the point on the path, but does not include $ lca $, so we added to the list in the contribution it $ lca $ at the time of recording the answer like, specific look at the code, like painting FIG.

Example: bzoj3052 candy Park

  We speak of the subject obtained transformed it, because no one wants to turning back, so the number is to ask a simple candy tree path between two points of $ \ times $ certain weight. Of course there is a modification operations that modify the tree with Mo team. This question is very simple, he is a simple modification with Mo Mo tree team plus the team.

#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std;
#define N 200010
struct Oper {int pla,to,old;}oper[N];
struct Ask {int l,r,ano,tim,id;}ask[N];
int position [N] F [20] [N], col [N], chan [N];
int n,m,q,idx,cnt,tot,in[N],out[N],l,r,t;
long long now,ans[N]; int level[N]; bool is[N];
int num1[N],num2[N],many[N],head[N],to[N],nxt[N],Siz;
void add(int a,int b)
	{nxt[++idx]=head[a],to[idx]=b,head[a]=idx;}
void dfs(int p,int from)
{
	in[p]=++cnt,place[cnt]=p;
	// printf("%d %d\n",p,cnt);
	fa[0][p]=from,level[p]=level[from]+1;
	for(int i=head[p];i;i=nxt[i]) if(to[i]!=from)
		dfs(to[i],p);
	out[p]=++cnt,place[cnt]=p;
}
int find_lca(int x,int y)
{
	if(level[x]>level[y]) swap(x,y);
	for(int i=19;~i;i--) if((1<<i)<=level[y]-level[x])
		y=fa[i][y];
	if(x==y) return x;
	for(int i=19;~i;i--) if(fa[i][x]!=fa[i][y])
		for x = [i] [x] = y ago [i] [y];
	return four [0] [x];
}
ask_bel (int, int x) {return x / (x +%! = 0);
bool cmp(const Ask &a,const Ask &b)
{
	return (ask_bel(a.l)==ask_bel(b.l))?
	(ask_bel(a.r)==ask_bel(b.r)?a.tim<b.tim:a.r<b.r):a.l<b.l;
}
void change(int x,int y)
{
	int tmp=num1[col[x]],tmp2=num1[y];
	if(in[x]<=r&&in[x]>=l) if(is[x])
		now-=1ll*tmp*num2[many[col[x]]],many[col[x]]--,
		many[y]++,now+=1ll*tmp2*num2[many[y]];
	if(out[x]<=r&&out[x]>=l) if(is[x])
		now-=1ll*tmp*num2[many[col[x]]],many[col[x]]--,
		many[y]++,now+=1ll*tmp2*num2[many[y]];
	al [x] = y;
}
void add(int x)
{
	if(is[x]) now-=1ll*num1[col[x]]*num2[many[col[x]]],many[col[x]]--,is[x]=false;
	else many[col[x]]++,now+=1ll*num1[col[x]]*num2[many[col[x]]],is[x]=true;
}
void del(int x)
{
	if(is[x]) now-=1ll*num1[col[x]]*num2[many[col[x]]],many[col[x]]--,is[x]=false;
	else many[col[x]]++,now+=1ll*num1[col[x]]*num2[many[col[x]]],is[x]=true;
}
int main ()
{
	scanf("%d%d%d",&n,&m,&q),Siz=pow(n,0.66666);
	for(int i=1;i<=m;i++) scanf("%d",&num1[i]);
	for(int i=1;i<=n;i++) scanf("%d",&num2[i]);
	for(int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x);
	dfs(1,0),cnt=0;
	for(int i=1;i<=19;i++) for(int j=1;j<=n;j++)
		four [c] [j] = four [i-1] [four [i-1] [j]];
	for(int i=1;i<=n;i++) scanf("%d",&col[i]),chan[i]=col[i];
	for(int i=1,type,x,y;i<=q;i++)
	{
		scanf("%d%d%d",&type,&x,&y);
		if(type==0) ++cnt,oper[cnt].pla=x,oper[cnt].to=y;
		else
		{
			int lca=find_lca(x,y);
			if(in[x]>in[y]) swap(x,y);
			++tot,ask[tot].l=out[x],ask[tot].r=in[y];
			if(lca!=x) ask[tot].ano=lca;
			else ask[tot].l=in[x],ask[tot].r=in[y];
			Ask [all] .tim = cnt, ask [all] .id = all;
		}
	}
	for(int i=1;i<=cnt;i++)
		oper[i].old=chan[oper[i].pla],chan[oper[i].pla]=oper[i].to;
	sort(ask+1,ask+tot+1,cmp);
	for(int i=1;i<=tot;i++)
	{
		while(t<ask[i].tim) ++t,change(oper[t].pla,oper[t].to);
		while(t>ask[i].tim) change(oper[t].pla,oper[t].old),t--;
		while(l>ask[i].l) --l,add(place[l]);
		while(r<ask[i].r) ++r,add(place[r]);
		while(l<ask[i].l) del(place[l]),l++;
		while(r>ask[i].r) del(place[r]),r--;
		ans[ask[i].id]=now;
		if(ask[i].ano)
			ans[ask[i].id]+=1ll*num1[col[ask[i].ano]]*num2[many[col[ask[i].ano]]+1];
	}
	for(int i=1;i<=tot;i++) printf("%lld\n",ans[i]);
}

  

Guess you like

Origin www.cnblogs.com/yangsongyi/p/11080945.html