【刷题记录】杂题记录
1.【bzoj 4552】[Tjoi2016&Heoi2016]排序
題意:給出一個(gè)1到n的全排列,現(xiàn)在對(duì)這個(gè)全排列序列進(jìn)行m次局部排序。排序分為兩種:(0,l,r)表示將區(qū)間[l,r]的數(shù)字升序排序;(1,l,r)表示將區(qū)間[l,r]的數(shù)字降序排序。最后詢問第q位置上的數(shù)字。
分析:二分答案,將所有值小于等于當(dāng)前值的數(shù)賦為0,其余賦為1。利用線段樹可以通過統(tǒng)計(jì)區(qū)間內(nèi)數(shù)字1的個(gè)數(shù)來(lái)使當(dāng)前區(qū)間有序。進(jìn)行m次局部排序后可以得到答案與當(dāng)前值的大小關(guān)系,滿足可二分性。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #define l(x) x<<1 5 #define r(x) x<<1|1 6 using namespace std; 7 const int N=1e5+10; 8 int n,m,now,L,R,pos,ans,sum; 9 int a[N],t[N*4],tag[N*4]; 10 struct node{int op,l,r;}b[N]; 11 int read() 12 { 13 int x=0,f=1;char c=getchar(); 14 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 15 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} 16 return x*f; 17 } 18 void up(int x){t[x]=t[l(x)]+t[r(x)];} 19 void dn(int x,int l,int r) 20 { 21 int mid=(l+r)>>1; 22 tag[l(x)]=tag[x];t[l(x)]=tag[x]*(mid-l+1); 23 tag[r(x)]=tag[x];t[r(x)]=tag[x]*(r-mid); 24 tag[x]=-1; 25 } 26 void build(int x,int l,int r) 27 { 28 tag[x]=-1; 29 if(l==r){t[x]=(a[l]>now);return;} 30 int mid=(l+r)>>1; 31 build(l(x),l,mid); 32 build(r(x),mid+1,r); 33 up(x); 34 } 35 void change(int x,int l,int r,int p) 36 { 37 if(l!=r&&tag[x]!=-1)dn(x,l,r); 38 if(L<=l&&R>=r){tag[x]=p;t[x]=p*(r-l+1);return;} 39 int mid=(l+r)>>1; 40 if(L<=mid)change(l(x),l,mid,p); 41 if(R>mid)change(r(x),mid+1,r,p); 42 if(l!=r)up(x); 43 } 44 void ask(int x,int l,int r) 45 { 46 if(l!=r&&tag[x]!=-1)dn(x,l,r); 47 if(L<=l&&R>=r){sum+=t[x];return;} 48 int mid=(l+r)>>1; 49 if(L<=mid)ask(l(x),l,mid); 50 if(R>mid)ask(r(x),mid+1,r); 51 } 52 int main() 53 { 54 n=read();m=read(); 55 for(int i=1;i<=n;i++)a[i]=read(); 56 for(int i=1;i<=m;i++) 57 b[i].op=read(),b[i].l=read(),b[i].r=read(); 58 pos=read(); 59 int l=1,r=n; 60 while(l<=r) 61 { 62 now=(l+r)>>1;build(1,1,n); 63 for(int i=1;i<=m;i++) 64 { 65 L=b[i].l;R=b[i].r; 66 sum=0;ask(1,1,n); 67 if(!b[i].op)sum=b[i].r-b[i].l+1-sum; 68 L=b[i].l;R=b[i].l+sum-1; 69 if(L<=R)change(1,1,n,b[i].op); 70 L=b[i].l+sum;R=b[i].r; 71 if(L<=R)change(1,1,n,1-b[i].op); 72 } 73 L=R=pos;sum=0;ask(1,1,n); 74 if(sum)l=now+1; 75 else ans=now,r=now-1; 76 } 77 printf("%d",ans); 78 return 0; 79 } View Code2.【bzoj 2144】跳跳棋
題意:棋盤上有3顆棋子,分別在a,b,c位置,目標(biāo)是通過最少的跳動(dòng)把他們的位置移成x,y,z。跳動(dòng)的規(guī)則即為任意選一顆棋子,對(duì)一顆中軸棋子跳動(dòng),跳動(dòng)后兩顆棋子距離不變。一次只允許跳過1顆棋子。首先判斷是否可以完成任務(wù);如果可以,輸出最少需要的跳動(dòng)次數(shù)。
分析:中間的棋子可以往兩側(cè)跳,但兩側(cè)的棋子只有一個(gè)能往中間跳(跟中間棋子距離較小的那一個(gè))。那么所有的狀態(tài)就能表示為一棵二叉樹,在樹上往下走即為中間向兩邊跳。問題轉(zhuǎn)換為給定樹上的兩個(gè)結(jié)點(diǎn),求其距離。在當(dāng)前狀態(tài)在樹上往上走的過程中利用了輾轉(zhuǎn)相除的思想。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 using namespace std; 5 const int inf=1e9; 6 int tmp,d1,d2,ans,a[4],b[4]; 7 struct node{int x[4];}t1,t2; 8 int read() 9 { 10 int x=0,f=1;char c=getchar(); 11 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 12 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} 13 return x*f; 14 } 15 node calc(int *a,int k)//兩邊向中間跳k次,即在樹上往上走k步 16 { 17 node ans; 18 int t1=a[2]-a[1],t2=a[3]-a[2]; 19 for(int i=1;i<=3;i++)ans.x[i]=a[i]; 20 if(t1==t2)return ans; 21 if(t1<t2)//左邊往中間跳 22 { 23 int t=min(k,(t2-1)/t1); 24 k-=t;tmp+=t;//tmp記錄深度,即實(shí)際步數(shù) 25 ans.x[2]+=t*t1;ans.x[1]+=t*t1; 26 } 27 else//右邊往中間跳 28 { 29 int t=min(k,(t1-1)/t2); 30 k-=t;tmp+=t; 31 ans.x[2]-=t*t2;ans.x[3]-=t*t2; 32 } 33 if(k)return calc(ans.x,k);//輾轉(zhuǎn)相除 34 return ans; 35 } 36 bool operator != (node a,node b) 37 { 38 for(int i=1;i<=3;i++) 39 if(a.x[i]!=b.x[i])return true; 40 return false; 41 } 42 int main() 43 { 44 for(int i=1;i<=3;i++)a[i]=read(); 45 for(int i=1;i<=3;i++)b[i]=read(); 46 sort(a+1,a+4);sort(b+1,b+4); 47 t1=calc(a,inf);d1=tmp;tmp=0; 48 t2=calc(b,inf);d2=tmp;tmp=0; 49 if(t1!=t2){printf("NO");return 0;} 50 if(d1>d2) 51 { 52 swap(d1,d2); 53 for(int i=1;i<=3;i++)swap(a[i],b[i]); 54 } 55 t2=calc(b,d2-d1); 56 for(int i=1;i<=3;i++)b[i]=t2.x[i];//調(diào)整到同一深度 57 int l=0,r=d1,mid; 58 while(l<=r) 59 { 60 mid=(l+r)>>1; 61 if(calc(a,mid)!=calc(b,mid))l=mid+1; 62 else r=mid-1; 63 } 64 printf("YES\n%d",d2-d1+2*l); 65 return 0; 66 } View Code?
轉(zhuǎn)載于:https://www.cnblogs.com/zsnuo/p/7498679.html
總結(jié)
以上是生活随笔為你收集整理的【刷题记录】杂题记录的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 将Excel的数据导入DataGridV
- 下一篇: Gym 101606 F-Flippin