试题描述
|
|
输入
|
第一行为一个整数m(1<=m<=1000000),
第二行包括m个用空格分开的整数ai(1<=ai<=1000000),组成了最初的序列, 第三行为一个整数n(1<=n<=1000000),表示n个陈思经过一系列删除得到的序列,每个序列两行,第一行给出长度L(1<=L<=m),然后下一行为L个由空格分开的整数bi(1<=bi<=1000000)。 |
输出
|
共n行,如果陈思的序列确实是由最初的序列删除一些数得到,就输出TAK,否则输出NIE。
|
输入示例
|
7
1 5 4 5 7 8 6 4 5 1 5 5 8 6 3 2 2 2 3 5 7 8 4 1 5 7 4 |
输出示例
|
TAK
NIE TAK NIE |
其他说明
|
二分2083
|
对每个权值建立位置的集合,如果用vector要写二分,如果用平衡树就直接lower_bound了。
vector,用now表示当前位置+1,下同(3979ms)
#include<cstdio> #include<cctype> #include<vector> #include<cstring> #include<algorithm> #define rep(s,t) for(int i=s;i<=t;i++) #define ren for(int i=first[x];i!=-1;i=next[i]) using namespace std; inline int read() { int x=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } const int maxn=1000010; vector<int> T[maxn]; int main() { int n=read(); rep(1,n) T[read()].push_back(i); int m=read(); while(m--) { int k=read(),now=1,ok=1; rep(1,k) { int v=read(); if(!T[v].size()||T[v][T[v].size()-1]<now) ok=0; else { int l=0,r=T[v].size()-1,mid; while(l<r) if(T[v][mid=l+r>>1]<now) l=mid+1; else r=mid; now=T[v][l]+1; } } if(ok) puts("TAK"); else puts("NIE"); } return 0; }
偷懒用set结果T飞了(TLE)
#include<cstdio> #include<cctype> #include<set> #include<cstring> #include<algorithm> #define rep(s,t) for(int i=s;i<=t;i++) #define ren for(int i=first[x];i!=-1;i=next[i]) using namespace std; inline int read() { int x=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } const int maxn=1000010; set<int> T[maxn]; set<int>::iterator it; int main() { int n=read(); rep(1,n) T[read()].insert(i); int m=read(); while(m--) { int k=read(),now=1,ok=1; rep(1,k) { int v=read(); if(!T[v].size()) ok=0; else { it=T[v].lower_bound(now); if(it==T[v].end()) ok=0; else now=(*it)+1; } } if(ok) puts("TAK"); else puts("NIE"); } return 0; }
STL太慢了,我们可以写一个数组,以权值为第一关键字,以位置为第二关键字排序,然后再上面继续二分。(827ms)
我竟然又WA了一发,越来越感觉要直播了。
#include<cstdio> #include<cctype> #include<set> #include<cstring> #include<algorithm> #define rep(s,t) for(int i=s;i<=t;i++) #define ren for(int i=first[x];i!=-1;i=next[i]) using namespace std; inline int read() { int x=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } const int maxn=1000010; struct Arr { int p,v; bool operator < (const Arr& ths) const { if(v!=ths.v) return v<ths.v; return p<ths.p; } }A[maxn]; int L[maxn],R[maxn]; int main() { int n=read(); rep(1,n) A[A[i].p=i].v=read(); sort(A+1,A+n+1); int cur=1; rep(1,1000000) { if(A[cur].v!=i) continue; L[i]=cur;while(A[cur+1].v==i) cur++;R[i]=cur++; } int m=read(); while(m--) { int k=read(),now=1,ok=1; rep(1,k) { int v=read();if(!L[v]||A[R[v]].p<now) ok=0; if(!ok) continue; int l=L[v],r=R[v],mid; while(l<r) if(A[mid=l+r>>1].p<now) l=mid+1; else r=mid; now=A[l].p+1; } if(ok) puts("TAK"); else puts("NIE"); } return 0; }