//RMQ+并查集,RMQ套模板即可,此题关键是并查集的使用 //sicily 1949 1876是同一道题,但是注意CASE的大小写,时间区别是5s和1s #include<iostream> #include<cmath> #include<cstring> using namespace std; int _max[100010][18],_min[100010][18]; bool ok; int father[100010]; int n,query,st,ed,u,v; void RMQ()//套模板即可 { for(int j = 1;(1<<j) <= n;++j) for(int i = 1;i + (1<<j) -1 <= n;++i) { _max[i][j] = max(_max[i][j-1],_max[i+(1<<(j-1))][j-1]); _min[i][j] = min(_min[i][j-1],_min[i+(1<<(j-1))][j-1]); } } int getfather(int x)//数据规模是10W,因此找爸爸这一步骤最好写成非递归形式 { int temp = x; while(x != father[x]) x = father[x]; father[temp] = x;//路径压缩 return x; } void connect(int x,int y)//如果X和Y的爸爸不同,就让他们拥有共同祖先 { x = getfather(x); y = getfather(y); if(x != y) father[y] = x; } int Max(int st,int ed) { int k = (int)(log((double)(ed - st + 1))/log(2.0)); return max(_max[st][k],_max[ed-(1<<k)+1][k]); } int Min(int st,int ed) { int k = (int)(log((double)(ed - st + 1))/log(2.0)); return min(_min[st][k],_min[ed-(1<<k)+1][k]); } int main() { //freopen("in.txt","r",stdin); int caseN = 0; bool first = 1; while(scanf("%d",&n) != EOF) { if(!first) printf("/n"); first = 0; for(int i = 1;i <= n;++i) father[i] = i; printf("Case %d/n",++caseN); for(int i = 1;i <= n;++i) { scanf("%d",&_max[i][0]); _min[i][0] = _max[i][0]; } RMQ(); scanf("%d",&query); while(query--) { scanf("%d%d",&st,&ed); u = Max(st,ed); v = Min(st,ed); connect(u,v); } scanf("%d",&query); while(query--) { scanf("%d%d",&u,&v); if(getfather(u) == getfather(v)) printf("YES/n"); else printf("NO/n"); } } return 0; }