luogu4155/bzoj4444 国旗计划 (倍增)

成环,把每个区间变成两个然后展开成链

一个人的下一个人肯定是在彼此相交的基础上,右端点越大越好

于是就把它连到相交的、右端点最大的点上,连成一棵树

于是每次只要从某个节点开始,一直在树上跳到覆盖了一个M为止,统计数量

这个可以倍增来做

 1 #include<bits/stdc++.h>
 2 #define pa pair<int,int>
 3 #define CLR(a,x) memset(a,x,sizeof(a))
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxn=4e5+10;
 7 
 8 inline ll rd(){
 9     ll x=0;char c=getchar();int neg=1;
10     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
12     return x*neg;
13 }
14 
15 struct Node{
16     ll l,r;int id;
17 }pos[maxn];
18 int N,M,ans[maxn];
19 int fa[maxn][20];
20 
21 inline bool cmp(Node a,Node b){return a.l<b.l;}
22 
23 int main(){
24     //freopen("","r",stdin);
25     int i,j,k;
26     N=rd(),M=rd();
27     for(i=1;i<=N;i++){
28         ll a=rd(),b=rd();
29         if(b<a) b+=M;
30         pos[i].id=i,pos[i+N].id=i+N;
31         pos[i].l=a,pos[i].r=b;
32         pos[i+N].l=a+M,pos[i+N].r=b+M;
33     }
34     sort(pos+1,pos+N*2+1,cmp);
35     for(i=N*2,j=N*2;i;i--){
36         for(;j>i+1&&pos[j].l>pos[i].r;j--);
37         if(j>i&&pos[j].l<=pos[i].r)
38             fa[i][0]=j;
39         // printf("%d %d\n",pos[i].id,pos[fa[i][0]].id);
40         for(k=0;fa[i][k]&&fa[fa[i][k]][k];k++)
41             fa[i][k+1]=fa[fa[i][k]][k];
42     }
43     for(i=1;i<=N;i++){
44         int x=i;
45         // printf("%d\n",pos[i].id);
46         for(j=18;j>=0;j--){
47             if(fa[x][j]&&pos[fa[x][j]].r<pos[i].l+M)
48                 ans[pos[i].id]+=(1<<j),x=fa[x][j];
49         }ans[pos[i].id]+=2;
50     }
51     for(i=1;i<=N;i++)
52         printf("%d ",ans[i]);
53     return 0;
54 }

 

posted @ 2018-10-09 10:36  Ressed  阅读(206)  评论(0编辑  收藏  举报