计蒜客 微软项目经理的挑选方案
来源:互联网 发布:天刀捏脸数据怎么下载 编辑:程序博客网 时间:2024/05/14 21:34
题目链接
题目大意
给定
题解
解题的方向肯定是先给区间排个序然后考虑dp.
我们将区间按左端点为第一关键词,右端点为第二关键词从小到大排序.
设第
为什么叫”支配”呢?
因为如果选了区间
那么我们的目标就变成了需要每个区间都被所选的区间支配到.
似乎有点问题?
请看下面的手绘渣图:
这样区间
然鹅因为最终区间
关于如何求每个
为了防止下标越界,不妨在首尾加入两个区间
由于是按左端点排序,所以所有区间满足左端点单调递增,于是可以二分求
而左边是求最大的下标
经过上面的分析,这个题目其实已经可以抛掉给出的区间不管了,完全转化成了序列上的dp问题.
接下来把原来的区间都看作点好了.
由于某种不可抗力,我们需要倒着dp(下面会解释原因).
令
这样的状态定义是充分的,因为倒着来的话
而如果正着来,就利用不了这个单调性,也就不好进行状态转移了(官方题解中是一开始把区间按右端点当做第一关键词排序然后正着dp的,道理是一样的).
显然第一维
dp的初始状态为
容易写出状态转移方程:
然后用线段树优化就可以了.
总的时间复杂度是
补:后来发现其实转化后的问题就是选出一些区间覆盖所有的点,重新给区间排序也不会有影响.
代码
注:其实deque是系统关键词,比较危险,请不要学我…
#include<cstdio>#include<cstring>#include<cassert>#include<algorithm>#define lowbit(x) (x&-x);#define fi first#define se secondusing namespace std;typedef pair<int,int> pii;const int N=(int)2e5+5,mod=(int)1e9+7,INF=0x7fffffff;int n,L[N],R[N],deque[N],pow_2[N];pii itv[N];struct Segment_Tree{ #define lson (k<<1) #define rson (k<<1|1) struct Node{ int L,R,Lsh_cnt,sum; }tree[N<<2]; void build(int L=0,int R=n,int k=1){ tree[k].L=L; tree[k].R=R; tree[k].Lsh_cnt=0; tree[k].sum=R==n; if(L==R)return; int mid=L+R>>1; build(L,mid,lson); build(mid+1,R,rson); } inline void push_up(int k){ if((tree[k].sum=tree[lson].sum+tree[rson].sum)>=mod) tree[k].sum-=mod; } inline void mod_Lsh(int &num,int cnt){ num=1ll*num*pow_2[cnt]%mod; } void push_down(int k){ if(!tree[k].Lsh_cnt)return; mod_Lsh(tree[lson].sum,tree[k].Lsh_cnt); mod_Lsh(tree[rson].sum,tree[k].Lsh_cnt); tree[lson].Lsh_cnt+=tree[k].Lsh_cnt; tree[rson].Lsh_cnt+=tree[k].Lsh_cnt; tree[k].Lsh_cnt=0; } int query_sum(int L,int R,int k=1){ if(tree[k].L==L&&tree[k].R==R) return tree[k].sum; push_down(k); int mid=tree[k].L+tree[k].R>>1; if(R<=mid)return query_sum(L,R,lson); if(L>mid)return query_sum(L,R,rson); int res=query_sum(L,mid,lson)+query_sum(mid+1,R,rson); if(res>=mod)res-=mod; return res; } void modify(int tar,int val,int k=1){ if(tree[k].L==tree[k].R){ tree[k].sum=val; return; } push_down(k); int mid=tree[k].L+tree[k].R>>1; if(tar<=mid)modify(tar,val,lson); else modify(tar,val,rson); push_up(k); } void Lsh(int L,int R,int k=1){ if(tree[k].L==L&&tree[k].R==R){ mod_Lsh(tree[k].sum,1); ++tree[k].Lsh_cnt; return; } push_down(k); int mid=tree[k].L+tree[k].R>>1; if(R<=mid)Lsh(L,R,lson); else if(L>mid)Lsh(L,R,rson); else{ Lsh(L,mid,lson); Lsh(mid+1,R,rson); } push_up(k); }}T;void rd(int &res){ res=0; char c; while(c=getchar(),c<48); do res=(res<<3)+(res<<1)+(c^48); while(c=getchar(),c>47);}void init(){ itv[n]=pii(0,0); itv[n+1]=pii(INF,INF); sort(itv,itv+n+2); int head=0,tail=0; deque[tail++]=0; for(int i=1;i<=n;++i){ for(int bin_L=i+1,bin_R=n+1;bin_L<=bin_R;){ int mid=bin_L+bin_R>>1; if(itv[mid].fi>itv[i].se){ R[i]=mid-1; bin_R=mid-1; } else bin_L=mid+1; } int bin_L=head,bin_R=tail-1,res; while(bin_L<=bin_R){ int mid=bin_L+bin_R>>1; if(itv[deque[mid]].se<itv[i].fi){ res=mid; bin_L=mid+1; } else bin_R=mid-1; } L[i]=deque[res]+1; head=res; while(head<tail&&itv[deque[tail-1]].se>=itv[i].se)--tail; deque[tail++]=i; } pow_2[0]=1; for(int i=1;i<=n;++i) if((pow_2[i]=pow_2[i-1]<<1)>=mod)pow_2[i]-=mod;}int main(){ rd(n); for(int i=0;i<n;++i){ rd(itv[i].fi); rd(itv[i].se); } init(); T.build(); for(int i=n;i;--i){ if(R[i]<n)T.Lsh(R[i]+1,n); T.modify(L[i]-1,(1ll*T.query_sum(L[i],R[i])+(T.query_sum(L[i]-1,L[i]-1)<<1))%mod); } printf("%d\n",T.query_sum(0,0)); return 0;}
- 计蒜客 微软项目经理的挑选方案
- 计蒜客 微软项目经理的挑选方案
- 怎样挑选优秀的项目经理
- 微软项目经理的定义
- 微软对项目经理的要求
- 亚洲微软研究院:如何挑选聪明头脑( Mark 下,讲的挺神的。。)
- 在微软我们怎样开发软件:一名准项目经理的视角
- 在微软我们怎样开发软件:一名准项目经理的视角
- 挑选万种vs 配色方案~~
- AJAX与微软的新方案
- AJAX与微软的新方案
- AJAX与微软的新方案
- 挑选适任的人才
- 论蜂蜜的挑选
- 微软的打包方案和Sun Java打包方案比较
- 挑选
- 挑选
- 提拔,培养软件项目经理方案
- 软件设计规划
- 教案、讲稿、讲义的区别
- APP开发流程实例讲解-儒释道网络电台八天开发全程-优化排错:增强稳定性和添加异常处理
- Go入门:怎样编写Go代码
- codeforces 375D Tree and Queries
- 计蒜客 微软项目经理的挑选方案
- ******Eclipse 快捷键******
- android 监控应用进程
- C++——指针和引用
- 【2029】亲和数对
- Problem4-1018
- PAT 1020. 月饼 (25)
- 5h2w
- ACM第四次练习—1013