EZOJ 网同14(蛋蛋与北大信科-Splay的颜色分离,寻找结点所在子树)

 

蛋蛋与北大信科

总时限 10s 内存限制 256MB
出题人 lydrainbowcat 提交情况 1/25

背景

琰琰(孩纸们读作:蛋蛋)是妙峰书苑的一名萌萌哒教师,她的夫君(孩纸们称之为:北大信科)是北京大学信息科学技术学院的毕业生。无聊之余,蛋蛋与北大信科就成了孩纸们调侃的对象。

描述

宝哥和宝妹是孩纸们当中一对恩爱的兄妹。有一天,宝哥送给宝妹一本名叫《蛋蛋与北大信科传》的小说,对这本书爱不释手的宝妹每天晚上都会读上几页。但是宝妹读书的方法非常特别。

《蛋蛋与北大信科传》一共M页,起初所有页都是没有标记的。第i天读书时,宝妹会手持一根颜色为i的水彩笔,并把这一天读过的页标记为颜色i。她每天选择一个区间[L,R],阅读在[L,R]中所有从未读过(没有标记)的页,以及[L,R]中所有与第L页上的标记颜色相同的页。读过的这些页会被重新标记颜色(颜色可以覆盖)。N天之后,宝妹想知道她一共读过了多少页书呢?

输入格式

第一行两个整数M、N。

接下来N行,每行两个整数L、R。第i+1行的两个数表示宝妹第i天选择的区间。

输出格式

一个整数,表示宝妹一共读了多少页书。

样例输入

15 5
1 6
4 8
2 7
10 12
7 13

样例输出

20

数据范围与约定

  • 对于20%的数据,1<=n,m<=1000。
  • 对于50%的数据,1<=n<=1000,1<=m<=100000。
  • 对于100%的数据,1<=n,m<=300000,1<=L<=R<=m。

样例解释

第一天宝妹读1~6页,标记上颜色1。第二天读4~8页,其中56和4颜色相同均为1,78未被标记,4~8读完后标记上颜色2。第三天读23两页,因为2~7中都有标记且只有3和2颜色一样,读完后2~3标记颜色为3。第四天读10~12页,标记上颜色4。第五天读789、13页,13页没有标记,89也和7页的颜色相同,读完后789、13标记颜色5。一共读了6+5+2+3+4=20页书。


 

 

上面丧心病狂

本题,建n棵Splay,每种颜色一棵

1.记得将2棵子树裁下(是裁下,不是取出所有结点),启发式合并。

2.记得记录某个结点所在子树(Important

   D了一天Bug就是上面那条导致我T

   后来改成裁又WA(没用修改结点所在子树)

   后来找lyd的标程看——原来只要记录根所在子树(智商拙计)


 

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#include<cmath>
#include<cctype>
#include<cassert>
#include<climits>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define RepD(i,n) for(int i=n;i>=0;i--)
#define MEM(a) memset(a,0,sizeof(a))
#define MEMI(a) memset(a,127,sizeof(a))
#define MEMi(a) memset(a,128,sizeof(a))
#define INF (2139062143)
#define F (1000000009)
#define MAXN (900000+10)
#define MAXM (900000+10)
typedef long long ll;
struct node
{
   int ch[2],siz,c,fa,no;
   node():siz(0),c(0),fa(0),no(0){ch[0]=ch[1]=0;}
   node(int _c):siz(1),c(_c),fa(0),no(0){ch[0]=ch[1]=0;}
   node(int _c,int _fa):siz(1),c(_c),fa(_fa),no(0){ch[0]=ch[1]=0;}
   void clear(int _no){siz=1,fa=0,no=_no,ch[0]=ch[1]=0;}
}a[MAXN];
int root[MAXM]={0};   //<-is color
void update(int x){ a[x].siz=a[a[x].ch[0]].siz+a[a[x].ch[1]].siz+1; }
void rotate(int x) //assume x has father
{
   int y=a[x].fa,z=a[y].fa;
   int p=a[x].c<a[y].c;
   if (z) 
      if (a[z].ch[0]==y) a[z].ch[0]=x;else a[z].ch[1]=x;
   
   a[y].ch[p^1]=a[x].ch[p];
   if (a[y].ch[p^1]) a[a[y].ch[p^1]].fa=y;
   a[x].ch[p]=y;
   a[y].fa=x,a[x].fa=z;
   update(y); 
}
void splay(int x,int p) //let x rotate to p
{
   while (a[x].fa!=p)
   {
      int y=a[x].fa,z=a[y].fa;
      if (z!=p)
         if ((a[y].ch[0]==x)^(a[z].ch[0]==y)) rotate(x);else rotate(y);
      rotate(x);
   }
   update(x);
}
void insert(int &x,int p)
{
   if (!x) {x=p;return;}
   bool p2=a[x].c<a[p].c;
   insert(a[x].ch[p2],p);a[a[x].ch[p2]].fa=x;   
   update(x);
}
int find(int x,int c)
{
   if (!x) return 0;
   if (c==a[x].c) return x;
   bool p=a[x].c<c;
   int k=find(a[x].ch[p],c);
   if (k) return k;
   if (a[x].c<c) return x;
   return 0;
}
int find2(int x,int c)
{
   if (!x) return 0;
   if (c==a[x].c) return x;
   bool p=a[x].c<c;
   int k=find2(a[x].ch[p],c);
   if (k) return k;
   if (a[x].c>c) return x;
   return 0;
}
int q[MAXN],tot=0;
void bfs(int x)
{
   if (!x) return ;
   bfs(a[x].ch[0]);
   q[++tot]=x;
   bfs(a[x].ch[1]);
}
void merge(int &x,int new_num)
{
   
   ForD(i,tot) 
   {
      int now=q[i];
      a[now].clear(new_num);
      insert(x,now);
      splay(now,0);
      
      x=now;      
   }   
}
int n,m;
int where[MAXN];
void print(int x)
{
   if (!x) return ;
   print(a[x].ch[0]);
   cout<<a[x].c<<' ';
   print(a[x].ch[1]);
}
int make_q(int x,int l,int r,bool is_y) //第x棵子树 [l,r]之间的加入q 
{
   int x1=find(root[x],l-1),x2=find2(root[x],r+1);
   splay(x1,0);
   root[x]=x1;where[x1]=x;
   splay(x2,x1);
   if (is_y)
   {
		bfs(a[x2].ch[0]);   
   	a[x2].ch[0]=0;update(x2);update(x1);
   	return 0;
   }
   else
   {
		int k=a[x2].ch[0];a[k].fa=a[x2].ch[0]=0;
      update(x2);update(x1);
		return k;   		
   }
}
void build(int &x,int l,int r)
{
   int m=l+r>>1;
   x=m;
   if (l<m) build(a[x].ch[0],l,m-1),a[a[x].ch[0]].fa=x;
   if (m<r) build(a[x].ch[1],m+1,r),a[a[x].ch[1]].fa=x;
   
   update(x);
}
int getroot(int x)
{
   while (a[x].fa) x=a[x].fa;
   return x;
}
int main()
{
// freopen("book.in","r",stdin);
   scanf("%d%d",&n,&m);
   For(i,n) a[i].c=i,a[i].siz=1;
   a[n+1].c=0,a[n+1].siz=1;a[n+2].c=n+1,a[n+2].siz=1;

   build(root[0],1,n);
   insert(root[0],n+1),insert(root[0],n+2);
   where[root[0]]=0;
   
   
   ll ans=0;
   For(i,m)
   {
	//  print(root[1]);cout<<endl;
      int l,r;
      scanf("%d%d",&l,&r);
      int f=where[getroot(l)];
      tot=0;
      make_q(0,l,r,1);root[i]=make_q(f,l,r,0);
      merge(root[i],i);
   // cout<<a[root[i]].siz<<endl;
      ans+=a[root[i]].siz;
      a[n+2+i]=node(0);a[n+2+i].no=i,a[n+2+m+i]=node(n+1),a[n+2+m+i].no=i;
      insert(root[i],n+2+i),insert(root[i],n+2+m+i);
      
      where[root[i]]=i;
   }
   cout<<ans<<endl;
   
// while(1);
   return 0;
}


 


 

你可能感兴趣的:(play)