bzoj5259: [Cerc2017]区间
还是很强的一个题 ORZ肉丝哥哥
对于两个相交区间,假如他们两个都是可行的,那么他们的交也可行,不然没可能两边都把它缺的补上
那么对于答案区间,向右找到第一个可行区间右端点覆盖询问区间,就是最优的
考虑扫描线,枚举右端点,对于当前还没有找到答案的询问,取左端点最大的去找答案
问题在于怎么快速判断一个区间是否可行
用max-min==R-L没有前途像我一样,要考虑其他性质
令i,i+1属于区间则对区间贡献1,假如[l,r]可行,那么它的权值就是r-l
那么开一棵线段树,表示每个位置到R的最大对数和+l,假如等于r说明是合法方案,求一下区间最大值和它的位置即可
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<queue> #define lc (now<<1) #define rc (now<<1|1) #define mid (ql+qr)/2 #define mx first #define pos second using namespace std; typedef pair<int,int> pp; const int _=1e2; const int maxn=1e5+_; const int fbin=(1<<17)+_; struct trnode{pp p;int la;}tr[2*fbin]; void update(int now){tr[now].p=max(tr[lc].p,tr[rc].p);} void pushdown(int now) { if(tr[now].la!=0) { tr[lc].p.mx+=tr[now].la;tr[lc].la+=tr[now].la; tr[rc].p.mx+=tr[now].la;tr[rc].la+=tr[now].la; tr[now].la=0; } } void bt(int now,int ql,int qr) { tr[now].p.mx=qr;tr[now].p.pos=qr; if(ql!=qr) { bt(lc,ql,mid); bt(rc,mid+1,qr); } } void add(int now,int ql,int qr,int l,int r,int w) { if(ql==l&&qr==r){tr[now].p.mx++,tr[now].la++;return ;} pushdown(now); if(r<=mid) add(lc,ql,mid,l,r,w); else if(mid+1<=l)add(rc,mid+1,qr,l,r,w); else add(lc,ql,mid,l,mid,w),add(rc,mid+1,qr,mid+1,r,w); update(now); } pp findmax(int now,int ql,int qr,int l,int r) { if(ql==l&&qr==r)return tr[now].p; pushdown(now); if(r<=mid) return findmax(lc,ql,mid,l,r); else if(mid+1<=l)return findmax(rc,mid+1,qr,l,r); else return max(findmax(lc,ql,mid,l,mid),findmax(rc,mid+1,qr,mid+1,r)); } int n,a[maxn],b[maxn]; struct query{int l,r,id;}q[maxn];int Q; pp as[maxn]; bool cmp(query q1,query q2){return q1.r<q2.r;} struct cmq{bool operator()(query q1,query q2){return q1.l<q2.l;}}; priority_queue<query,vector<query>,cmq>p; int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[a[i]]=i; scanf("%d",&Q); for(int i=1;i<=Q;i++) scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i; sort(q+1,q+Q+1,cmp); int tp=1; bt(1,1,n); int x;query tq;pp tt; for(int i=1;i<=n;i++) { if(a[i]!=1) { x=b[a[i]-1]; if(x<i)add(1,1,n,1,x,i); } if(a[i]!=n) { x=b[a[i]+1]; if(x<i)add(1,1,n,1,x,i); } while(tp<=n&&q[tp].r==i)p.push(q[tp]),tp++; while(!p.empty()) { tq=p.top(); tt=findmax(1,1,n,1,tq.l); if(tt.first==i) { as[tq.id]=make_pair(tt.pos,i); p.pop(); } else break; } } for(int i=1;i<=Q;i++)printf("%d %d\n",as[i].mx,as[i].pos); return 0; }
pain and happy in the cruel world.