总时限 | 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
第一天宝妹读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; }