z总j结
考试开始看到几个大字:Day1
Happy~(××终于不用爆〇了哈哈哈哈!!)
开T1。一看,不是在线仙人球嵌套动态网络路径剖分优化的分支定界贪心剪枝启发式迭代加深人工智能搜索决策算法么……好!
码完一看,过不了大阳历……
发现贪心错了。
于是马上……(×××的day1)
看T2。
发现是数学,研究一番,推了一番柿子,然后就弃了。
这时我有点慌了(开考$1h$啥都没打??)
于是马上看T3(?)
暴力好打$\text{QvQ}$
打完T3回去想了下T1
码了一个$\Theta(N^2\log N)$的法子(全是在线仙人球嵌套动态网络路径剖分优化的分支定界贪心剪枝启发式迭代加深人工智能搜索决策算法)
然后T2的暴力也出来了。
最后是……
28 | Miemeng | 70 03:11:56 | 30 03:11:57 | 50 03:11:57 | 150 03:11:57 |
T1
法1
讲个我的$\Theta(N^2\log N)$
想到了让点找段,但是没来得及打。
于是我让段找点。
但是从左往右扫一定会死,因为贪心……
于是我想到可以维护段内的点数来贪。
从内部点数最少的段向更大的段贪。
每次修改都要重新计算和 sort
交上去$70$
(话说为啥本地对拍一直WA)
#include <algorithm> #include <iostream> #include <climits> #include <cstring> #include <cstdio> #define N 222222 using namespace std; struct Seg{ int l,r; int pn; }dse[N]; int dpo[N],sen,pon,ans=0; bool is_del[N]; int findv(int val){ return lower_bound(dpo+1,dpo+pon+1,val)-dpo; } inline bool CMP(const Seg &a,const Seg &b){ return a.pn<b.pn; } int main(){ // freopen("dream.in" ,"r",stdin);\ freopen("dream.out","w",stdout); scanf("%d%d",&sen,&pon); for(int i=1;i<=sen;i++) scanf("%d%d",&dse[i].l,&dse[i].r); for(int i=1;i<=pon;i++) scanf("%d",dpo+i); sort(dpo+1,dpo+pon+1); for(int i=1;i<=sen;i++){ dse[i].pn=findv(dse[i].r+1)-findv(dse[i].l); } sort(dse+1,dse+sen+1,CMP); for(int i=1;i<=sen;i++){ // cout<<dse[i].l<<" "<<dse[i].r<<" "<<dse[i].pn<<endl; int l=findv(dse[i].l), r=findv(dse[i].r+1); bool is_c=0; // cout<<"["<<dpo[l]<<","<<dpo[r]<<")"<<endl; if(l<r){ // cout<<i<<" ++++ "<<endl; is_c=1; dpo[l]=INT_MAX; ans++; } if(is_c){ sort(dpo+1,dpo+pon+1); for(int k=i+1;k<=sen;k++){ dse[k].pn=findv(dse[k].r+1)-findv(dse[k].l); } sort(dse+i+1,dse+sen+1,CMP); } } printf("%d\n",ans); }
正解……
点找段,堆优化……
首先对于每一个懵点,从左到右扫,一定是能覆盖它且右端点更靠左的更优。
于是用堆优化这个过程。
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <queue> #define N 222222 using namespace std; struct Seg{ int l,r; friend bool operator < (const Seg &a,const Seg &b){ return a.r>b.r; } }seg[N]; int sen,pn; void pour(priority_queue<Seg>s){ puts("---------===VV===----------"); while(!s.empty()){ cout<<s.top().l<<" "<<s.top().r<<endl; s.pop(); } puts("---------===^^===----------"); } priority_queue<Seg>q; int po[N],ans=0; int main(){ scanf("%d%d",&sen,&pn); for(int i=1;i<=sen;i++) scanf("%d%d",&seg[i].l,&seg[i].r); for(int i=1;i<=pn;i++) scanf("%d",po+i); sort(po+1,po+pn+1); sort(seg+1,seg+sen+1,[](const Seg &a,const Seg &b){return a.l<b.l;}); int sid=1; for(int i=1;i<=pn;i++){ while(sid<=sen && seg[sid].l<=po[i])q.push(seg[sid]),sid++; while(!q.empty() && q.top().r<po[i])q.pop(); if(!q.empty() && q.top().l<=po[i] && po[i]<=q.top().r){ ans++; q.pop(); } } printf("%d\n",ans); }