码迷,mamicode.com
首页 > 其他好文 > 详细

loj2048 「HNOI2016」最小公倍数

时间:2018-04-27 16:44:22      阅读:199      评论:0      收藏:0      [点我收藏+]

标签:cpp   namespace   printf   for   bool   --   can   hnoi   noi   

这竟然是一道分块题……

#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int n, m, q, blc, qnt, fa[50005], mxa[50005], mxb[50005], sz[50005], bcj, ans[50005];
struct Node{
    int uu, uv, ux, uy, uz;
}a[100005], b[50005], que[50005];
struct Bnode{
    int aa, bb, cc, dd, ee, ff;
}bn[100005];
bool cma(const Node &x, const Node &y){
    if(x.ux==y.ux)  return x.uy<y.uy;
    return x.ux<y.ux;
}
bool cmb(const Node &x, const Node &y){
    if(x.uy==y.uy)  return x.ux<y.ux;
    return x.uy<y.uy;
}
int myfind(int x){
    return fa[x]==x?x:myfind(fa[x]);
}
void merge(int uu, int uv, int uw, int ux){
    uu = myfind(uu); uv=myfind(uv);
    if(sz[uu]<sz[uv])   swap(uu, uv);
    bn[++bcj] = (Bnode){uu, uv, fa[uv], sz[uu], mxa[uu], mxb[uu]};
    if(uu==uv){
        mxa[uu] = max(mxa[uu], uw);
        mxb[uu] = max(mxb[uu], ux);
        return ;
    }
    fa[uv] = uu; sz[uu] += sz[uv];
    mxa[uu] = max(mxa[uu], max(mxa[uv], uw));
    mxb[uu] = max(mxb[uu], max(mxb[uv], ux));
}
int main(){
    cin>>n>>m;
    blc = sqrt(m);
    for(int i=1; i<=m; i++)
        scanf("%d %d %d %d", &a[i].uu, &a[i].uv, &a[i].ux, &a[i].uy);
    cin>>q;
    for(int i=1; i<=q; i++){
        scanf("%d %d %d %d", &b[i].uu, &b[i].uv, &b[i].ux, &b[i].uy);
        b[i].uz = i;
    }
    sort(a+1, a+1+m, cma);
    sort(b+1, b+1+q, cmb);
    for(int i=1; i<=m; i+=blc){
        qnt = 0;
        for(int j=1; j<=q; j++)
            if(b[j].ux>=a[i].ux && (i+blc>m || b[j].ux<a[i+blc].ux))
                que[++qnt] = b[j];
        int r=1;
        for(int j=1; j<=n; j++){
            fa[j] = j;
            sz[j] = 1;
            mxa[j] = mxb[j] = -1;
        }
        sort(a+1, a+i+1, cmb);
        for(int j=1; j<=qnt; j++){
            for(; r<i && a[r].uy<=que[j].uy; r++)
                merge(a[r].uu, a[r].uv, a[r].ux, a[r].uy);
            bcj = 0;
            for(int k=i; k<i+blc && k<=m; k++)
                if(a[k].ux<=que[j].ux && a[k].uy<=que[j].uy)
                    merge(a[k].uu, a[k].uv, a[k].ux, a[k].uy);
            int x=myfind(que[j].uu), y=myfind(que[j].uv);
            if(x==y && mxa[x]==que[j].ux && mxb[x]==que[j].uy)
                ans[que[j].uz] = 1;
            for(int i=bcj; i>=1; i--){
                int xx=bn[i].aa, yy=bn[i].bb;
                fa[yy] = bn[i].cc;
                sz[xx] = bn[i].dd;
                mxa[xx] = bn[i].ee; mxb[xx] = bn[i].ff;
            }
        }
    }
    for(int i=1; i<=q; i++)
        printf(ans[i]?"Yes\n":"No\n");
    return 0;
}

loj2048 「HNOI2016」最小公倍数

标签:cpp   namespace   printf   for   bool   --   can   hnoi   noi   

原文地址:https://www.cnblogs.com/poorpool/p/8963012.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!