[***]HZOJ 优美序列
又是一道神仙題。考試的時(shí)候居然打了一個(gè)回滾莫隊(duì),不知道我咋想的……
先說一個(gè)某OJT80,洛谷T5分的思路(差距有點(diǎn)大):
可以把位置和編號(hào)映射一下,區(qū)間內(nèi)最大值和最小值對(duì)應(yīng)的位置,每次更新,直到找到符合條件的情況,復(fù)雜度玄學(xué)。最值的維護(hù)可以用ST表或者線段樹,前者復(fù)雜度低些。
然后說正解吧:
先放出來看不懂的作者的正解:
分治法,離線處理。假設(shè)現(xiàn)在處理的詢問都包含在[L,R]?中,設(shè)mid=(L+R)/2。然后將包含在[L,mid],[mid+1,R]?的區(qū)間分治處理。剩下的就是包含[mid,mid+1]?[mid,mid+1]的詢問,然后找出包含[mid,mid+1]?[mid,mid+1]的所有優(yōu)美區(qū)間,用這些優(yōu)美區(qū)間更新詢問的答案。
時(shí)間復(fù)雜度O(n(logn)^2)。
上面的我不會(huì)。
然后正解1:scc+線段樹優(yōu)化建圖
但是我不會(huì)……
正解2:
掃描線+轉(zhuǎn)化思想+線段樹,雖然我不會(huì)掃描線(我還以為這玩意只能用到二維呢)……
1.好的區(qū)間的交也是好的區(qū)間
2.好的區(qū)間的并也是好的區(qū)間
好的區(qū)間的判斷條件:maxn-minn=r-l,但是這樣并不夠,如果只是這樣判斷的話,就回到了80分的思路,不斷拓展區(qū)間判斷。
另一個(gè)判斷條件是l+num=r,num為區(qū)間中形如(a,a+1)這樣的點(diǎn)對(duì)數(shù)(將區(qū)間排序后就很顯然了)。
所以我們離線將詢問排序扔到set里,固定r,然后用線段樹維護(hù)左邊的信息及對(duì)應(yīng)的l,令葉子節(jié)點(diǎn)的初始值為l,查詢只需要找線段樹中滿足條件最靠右的,而每次r右移,給1~b[a[r]+-1]的區(qū)間的點(diǎn)對(duì)數(shù)+1,當(dāng)然要判斷一下,必須在它左邊。
其實(shí)我開始有一個(gè)問題,如果固定r,能保證區(qū)間的右端點(diǎn)一定是r嗎?顯然是不能的,但是在處理r時(shí),如果沒有滿足條件的l,這個(gè)詢問就會(huì)被剩到set中,在r+1后繼續(xù)更新,就保證了正確性。
1 #include<algorithm> 2 #include<iostream> 3 #include<cstdio> 4 #include<set> 5 #define LL long long 6 #define MAXN 1000010 7 using namespace std; 8 struct ques 9 { 10 int l,r,id; 11 friend bool operator < (ques a,ques b) 12 {return a.l==b.l?(a.r==b.r?a.id<b.id:a.r>b.r):a.l>b.l;} 13 }q[MAXN]; 14 set<ques> s; 15 set<ques>::iterator it; 16 pair<int,int>ans[MAXN]; 17 int n,m,a[MAXN],b[MAXN]; 18 struct po 19 { 20 int mx,id; 21 friend bool operator < (po a,po b) 22 {return a.mx==b.mx?a.id<b.id:a.mx<b.mx;} 23 }; 24 struct tree 25 { 26 po v;int ad,l,r; 27 #define l(x) tr[x].l 28 #define r(x) tr[x].r 29 #define ad(x) tr[x].ad 30 #define v(x) tr[x].v 31 #define ls(x) (x<<1) 32 #define rs(x) (ls(x)+1) 33 }tr[MAXN*4]; 34 void pushup(int x) 35 { 36 v(x)=max(v(ls(x)),v(rs(x))); 37 } 38 void down(int x) 39 { 40 if(!ad(x))return; 41 ad(ls(x))+=ad(x); 42 ad(rs(x))+=ad(x); 43 v(ls(x)).mx+=ad(x); 44 v(rs(x)).mx+=ad(x); 45 ad(x)=0; 46 } 47 void build(int x,int l,int r) 48 { 49 l(x)=l,r(x)=r; 50 if(l==r) 51 {v(x).id=v(x).mx=l;ad(x)=0;return;} 52 int mid=(l+r)>>1; 53 build(ls(x),l,mid); 54 build(rs(x),mid+1,r); 55 pushup(x); 56 } 57 void add(int x,int l,int r,int y) 58 { 59 if(l(x)>=l&&r(x)<=r) 60 {v(x).mx+=y;ad(x)+=y;return;} 61 down(x); 62 int mid=(l(x)+r(x))>>1; 63 if(l<=mid)add(ls(x),l,r,y); 64 if(r>mid) add(rs(x),l,r,y); 65 pushup(x); 66 } 67 po ask(int x,int l,int r) 68 { 69 down(x); 70 if(l(x)>=l&&r(x)<=r)return v(x); 71 int mid=(l(x)+r(x))>>1;po ans={-1,-1}; 72 if(l<=mid)ans=max(ans,ask(ls(x),l,r)); 73 if(r>mid) ans=max(ans,ask(rs(x),l,r)); 74 return ans; 75 } 76 bool cmp(ques a,ques b) 77 { 78 return a.r<b.r; 79 } 80 inline int read(); 81 signed main() 82 { 83 // freopen("in.txt","r",stdin); 84 85 n=read(); 86 for(int i=1;i<=n;i++)a[i]=read(),b[a[i]]=i; 87 m=read(); 88 for(int i=1;i<=m;i++)q[i].l=read(),q[i].r=read(),q[i].id=i; 89 sort(q+1,q+m+1,cmp); 90 build(1,1,n); 91 int ptr=1; 92 for(int i=1;i<=n;i++) 93 { 94 while(ptr<=m&&q[ptr].r==i) 95 s.insert(q[ptr]),ptr++; 96 if(a[i]>1&&b[a[i]-1]<i)add(1,1,b[a[i]-1],1); 97 if(a[i]<n&&b[a[i]+1]<i)add(1,1,b[a[i]+1],1); 98 while(s.size()) 99 { 100 ques now=*s.begin(); 101 po tem=ask(1,1,now.l); 102 if(tem.mx!=i)break; 103 ans[now.id].first=tem.id; 104 ans[now.id].second=i; 105 s.erase(now); 106 } 107 } 108 for(int i=1;i<=m;i++) 109 printf("%d %d\n",ans[i].first,ans[i].second); 110 } 111 inline int read() 112 { 113 int s=0;char a=getchar(); 114 while(a<'0'||a>'9')a=getchar(); 115 while(a>='0'&&a<='9'){s=s*10+a-'0',a=getchar();} 116 return s; 117 } View Code?聲討某ex_face一干人等卡分快調(diào)塊長卡掉數(shù)據(jù)
轉(zhuǎn)載于:https://www.cnblogs.com/Al-Ca/p/11306657.html
總結(jié)
以上是生活随笔為你收集整理的[***]HZOJ 优美序列的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [***]HZOJ 跳房子
- 下一篇: cnblogs第一篇