1. 程式人生 > >Origami(想法摺紙 樹狀陣列)

Origami(想法摺紙 樹狀陣列)

原題: 位元組跳動冬令營網路賽B

題意:

有一段繩子,上面有1~n個點,你可以在一個地方摺疊這個繩子,問最後能否折成給出的結果

解析:

上張圖說明一切
在這裡插入圖片描述
所以只需要判斷上面部分有沒有交叉,下面部分有沒有交叉即可

這個用樹狀陣列,判斷每一段中的左端點數量是否等於右端點數量

#include<bits/stdc++.h>
using namespace std;
#define LL long long
int pos[1000009];
bool vis[1000009];

int zero[1000009];
int one[1000009];

void add(int *ar,int
pos,int n){ while(pos<=n){ ar[pos]++; pos+=pos&(-pos); } } int query(int *ar,int pos){ int ans=0; while(pos>0){ ans+=ar[pos]; pos-=pos&(-pos); } return ans; } int main(){ int t;scanf("%d",&t); while(t--){ int n;
scanf("%d",&n); for(int i=1;i<=n;i++){ int tmp;scanf("%d",&tmp); pos[tmp]=i; } for(int i=1;i<=n;i++)vis[i]=0; int cant=0; for(int i=1;i<=n;i++)zero[i]=one[i]=0; for(int i=1;i<n;i+=2){ if(i+1>n)break
; int x=pos[i],y=pos[i+1]; if(x>y)swap(x,y); if(vis[x]||vis[y]){cant=1;break;} add(zero,x,n); add(one,y,n); } if(cant){ printf("No\n"); continue; } for(int i=1;i<n;i+=2){ if(i+1>n)break; int x=pos[i],y=pos[i+1]; if(x>y)swap(x,y); int z=query(zero,y-1)-query(zero,x); int o=query(one,y-1)-query(one,x); if(z!=o){ cant=1;break; } } if(cant){ printf("No\n"); continue; } for(int i=1;i<=n;i++)vis[i]=0; cant=0; for(int i=1;i<=n;i++)zero[i]=one[i]=0; for(int i=2;i<n;i+=2){ if(i+1>n)break; int x=pos[i],y=pos[i+1]; if(x>y)swap(x,y); if(vis[x]||vis[y]){cant=1;break;} add(zero,x,n); add(one,y,n); } if(cant){ printf("No\n"); continue; } for(int i=2;i<n;i+=2){ if(i+1>n)break; int x=pos[i],y=pos[i+1]; if(x>y)swap(x,y); int z=query(zero,y-1)-query(zero,x); int o=query(one,y-1)-query(one,x); if(z!=o){ cant=1;break; } } if(cant){ printf("No\n"); continue; } printf("Yes\n"); } }