acwing 智商药
题目链接:5046. 智商药 - AcWing题库
首先考虑dfs
不用想肯定超时 过了10/17个测试点
代码
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 typedef pair<int,int> PII; 5 typedef long long ll; 6 const int N=1e5+10,M=2*N; 7 const int p=1e9+7; 8 ll n,m; 9 struct node 10 { 11 int l, r; 12 13 }med[N]; 14 bool st[N]; 15 ll res=0; 16 void dfs(ll u) 17 { 18 if(u>n) return ; 19 //cout<<u<<endl; 20 if(u==n) 21 { 22 res++; 23 return ; 24 } 25 for(int i=1;i<=m;i++) 26 { 27 if(!st[i]&&med[i].l<=u&&u<=med[i].r-1) 28 { 29 st[i]=true; 30 dfs(med[i].r); 31 st[i]=false; 32 } 33 } 34 } 35 void solve() 36 { 37 cin>>n>>m; 38 for(int i=1;i<=m;i++) 39 cin>>med[i].l>>med[i].r; 40 sort(med+1,med+1+m,[](struct node a,struct node b)->bool {return a.l==b.l?a.r<b.r:a.l<b.l;}); 41 //for(int i=1;i<=m;i++) cout<<med[i].l<<' '<<med[i].r<<endl; 42 dfs(0); 43 cout<<res<<endl; 44 45 } 46 int main() 47 { 48 int T = 1; 49 //cin >> T; 50 while(T --) 51 { 52 solve(); 53 } 54 return 0; 55 }
然后考虑dp
注意到n最大为1e9,肯定不能作为下标,m=1e5,可以考虑,f[i]的表示的集合为只用前i种药,且一定会吃第i种药,属性为集合中的方案数
f[i]=sum(第i-1满足的条件之和) 因为吃药会变成med.r一定要按照r排序,也注意到第i-1满足条件的一定是一个区间,可以用树状数组,因为med.r为递增,也可以前缀和
0为特殊的药(0,0),前缀和习惯从1开始,所以可以从2开始读入每条边,后排序,枚举每个药品,找到前面能吃到这个药l-1的区间左右端点,进行二分,在进行f的前缀区间累加
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 #define endl "\n"; 5 typedef pair<int,int> PII; 6 typedef long long ll; 7 const int N=1e5+10,M=2*N; 8 const int p=1e9+7; 9 ll n,m; 10 struct node 11 { 12 int l, r; 13 14 }med[N]; 15 ll f[N],s[N]; 16 ll res; 17 int getl(int x) 18 { 19 int l=1,r=m+1; 20 while(l<r) 21 { 22 int mid=l+r>>1; 23 if(med[mid].r>=x) r=mid; 24 else l=mid+1; 25 } 26 return l; 27 } 28 int getr(int x) 29 { 30 int l=1,r=m+1; 31 while(l<r) 32 { 33 int mid=l+r+1>>1; 34 if(med[mid].r<=x) l=mid; 35 else r=mid-1; 36 } 37 return l; 38 } 39 void solve() 40 { 41 cin>>n>>m; 42 for(int i=2;i<=m+1;i++) cin>>med[i].l>>med[i].r; 43 sort(med+1,med+2+m,[](struct node a,struct node b)->bool {return a.r<b.r;}); 44 //for(int i=1;i<=m;i++) cout<<med[i].l<<' '<<med[i].r<<endl; 45 f[1]=1,s[1]=1; 46 for(int i=2;i<=m+1;i++) 47 { 48 int l=getl(med[i].l),r=getr(med[i].r-1); 49 //s[i]=s[i-1]; 50 f[i]=(s[r]-s[l-1])%p; 51 s[i]=(s[i-1]+f[i])%p; 52 if(med[i].r==n) res=(res+f[i])%p; 53 } 54 cout<<(res+p)%p<<endl; 55 } 56 int main() 57 { 58 ios::sync_with_stdio(false); 59 cin.tie(0); 60 int T = 1; 61 //cin >> T; 62 while(T --) 63 { 64 solve(); 65 } 66 return 0; 67 }
关闭流同步后运行时间447ms,之前是878ms,最后负数取模还是负数,可以+p后%p得到答案
本文作者:zouyua
本文链接:https://www.cnblogs.com/ZouYua/p/17527121.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步