답안 #225495

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
225495 2020-04-20T16:09:37 Z nicolaalexandra Colors (RMI18_colors) C++14
78 / 100
3000 ms 199916 KB
#include <bits/stdc++.h>
#define DIM 300010
#define INF 2000000000
using namespace std;
vector <int> L[DIM],poz[DIM*4],poz_a[DIM],poz_b[DIM];
int a[DIM],b[DIM],f[DIM],f2[DIM],c[DIM],v[DIM],viz[DIM],E[DIM*4],first[DIM],level[DIM],p[DIM*4],idx[DIM];
int mrk[DIM],fth[DIM],Size[DIM];
int t,n,m,i,j,x,y,k,sol,mini,maxi,ok,g,sol_final;
struct seg_tree{
    int minia,maxib;
} aint[4*DIM];
struct idk{
    int nod, minia, maxib;
} dp[DIM][30];
pair <int,int> rmq[30][DIM*4];

vector <pair<int,int> > aint2[DIM*4];
deque <pair<int,int> > s;

void dfs (int nod){
    viz[nod] = 1;
    v[++k] = nod;
    for (auto vecin : L[nod])
        if (!viz[vecin])
            dfs (vecin);
}
void build (int nod, int st, int dr){
    if (st == dr){
        aint[nod].minia = a[v[st]];
        aint[nod].maxib = b[v[st]];
        return;
    }
    int mid = (st+dr)>>1;
    build (nod<<1,st,mid);
    build ((nod<<1)|1,mid+1,dr);
    aint[nod].minia = min (aint[nod<<1].minia,aint[(nod<<1)|1].minia);
    aint[nod].maxib = max (aint[nod<<1].maxib,aint[(nod<<1)|1].maxib);
}
void query (int nod, int st, int dr, int x, int y){

    if (x <= st && dr <= y){
        mini = min (mini,aint[nod].minia);
        maxi = max (maxi,aint[nod].maxib);
        return;
    }
    int mid = (st+dr)>>1;
    if (x <= mid)
        query(nod<<1,st,mid,x,y);
    if (y > mid)
        query ((nod<<1)|1,mid+1,dr,x,y);
}
int solve (int v[], int k){
    for (i=1;i<=4*k;i++){
        poz[i].clear();
        aint[i] = {0,0};
    }

    for (i=1;i<=k;i++)
        poz[a[v[i]]].push_back(i);

    build (1,1,k);

    int ok = 1;

    for (i=1;i<=k;i++){
        if (a[v[i]] == b[v[i]])
            continue;

        int lft = 0, rgh = 0;
        for (auto it : poz[b[v[i]]]){
            if (it < i)
                lft = it;
            if (it > i){
                rgh = it;
                break;
            }
        }

        int ok2 = 0;
        if (lft){
            mini = INF, maxi = -INF;
            query (1,1,k,lft,i-1);
            if (mini >= b[v[i]] && maxi <= b[v[i]])
                ok2 = 1;
        }
        if (rgh){
            mini = INF, maxi = -INF;
            query (1,1,k,i+1,rgh);
            if (mini >= b[v[i]] && maxi <= b[v[i]])
                ok2 = 1;
        }

        if (!ok2){
            ok = 0;
            break;
        }}
    return ok;
}

void dfs2 (int nod){
    viz[nod] = 1;
    if (nod != i && a[nod] == b[i])
        g = 1;
    for (auto vecin : L[nod])
        if (!viz[vecin])
            if (a[vecin] >= b[i] && b[vecin] <= b[i])
                dfs2 (vecin);
}

void dfs3 (int nod, int tata){
    dp[nod][0] = {tata, a[nod],b[nod]};
    E[++k] = nod;
    first[nod] = k;
    level[nod] = 1 + level[tata];
    for (auto vecin : L[nod])
        if (vecin != tata){
            dfs3 (vecin,nod);
            E[++k] = nod;
        }
}

int get_lca (int x, int y){
    int posx = first[x], posy = first[y];
    if (posx > posy)
        swap (posx,posy);
    int nr = p[posy - posx + 1];
    pair <int, int> sol = min (rmq[nr][posx], rmq[nr][posy - (1<<nr) + 1]);
    return E[sol.second];
}

void solve2 (int x, int y){

    int lca = get_lca (x,y);
    for (int i=20;i>=0;i--){
        if (dp[x][i].nod && level[dp[x][i].nod] >= level[lca]){
            mini = min (mini,dp[x][i].minia);
            maxi = max (maxi,dp[x][i].maxib);
            x = dp[x][i].nod;
        }}

    for (int i=20;i>=0;i--){
        if (dp[y][i].nod && level[dp[y][i].nod] >= level[lca]){
            mini = min (mini,dp[y][i].minia);
            maxi = max (maxi,dp[y][i].maxib);
            x = dp[y][i].nod;
        }}}

void update_aint (int nod, int st, int dr, int x, int y, int a, int b){
    if (x <= st && dr <= y){
        aint2[nod].push_back(make_pair(a,b));
        return;
    }
    int mid = (st+dr)>>1;
    if (x <= mid)
        update_aint(nod<<1,st,mid,x,y,a,b);
    if (y > mid)
        update_aint ((nod<<1)|1,mid+1,dr,x,y,a,b);
}

int get_rad (int x){
    while (x != fth[x])
        x = fth[x];
    return x;
}

void unite (int radx, int rady){
    if (radx == rady)
        return;

    if (Size[radx] < Size[rady]);
        swap (radx,rady);

    /// tin minte o stiva cu update urile pe care le fac ca sa pot sa fac undo
    s.push_back(make_pair(radx,rady));

    Size[radx] += Size[rady];
    fth[rady] = radx;

}

void undo (){

    int x = s.back().first, y = s.back().second;
    s.pop_back();
    Size[x] -= Size[y];
    fth[y] = y;

}

void query_aint (int nod, int st, int dr){
    /// am intrat prima oara in nod, trb sa adaug muchiile
    int size_init = s.size(); /// ca sa stiu dupa cate undo uri trb sa fac

    for (auto it : aint2[nod]){
        int x = it.first, y = it.second;
        int radx = get_rad (x), rady = get_rad (y);
        unite (radx,rady);
    }

    if (st == dr){ /// acum trb sa fac query ul
        /// marchez culorile de a
        for (auto it : poz_a[st])
            mrk[get_rad(it)] = st;

        for (auto it : poz_b[st])
            if (mrk[get_rad(it)] != st){
                sol_final = 0;
                break;
            }
        return;
    }
    int mid = (st+dr)>>1;
    query_aint(nod<<1,st,mid);
    query_aint((nod<<1)|1,mid+1,dr);

    /// am terminat cu nod, trb sa dau undo
    int size_fin = s.size();
    for (int i=size_fin;i>size_init;i--)
        undo();
}

int main (){

   // ifstream cin ("colors2.in");
   // ofstream cout ("colors2.out");

    cin>>t;
    for (int q=1;q<=t;q++){
        //if (q == 36)
          //  q = 36;
        cin>>n>>m;


        for (i=1;i<=n;i++){
            L[i].clear();
            poz_a[i].clear();
            poz_b[i].clear();
            f[i] = 0;
        }
        for (i=1;i<=4*n;i++)
            aint2[i].clear();

        for (i=1;i<=n;i++){
            cin>>a[i];
            f[a[i]]++;
        }

        int ok = 1;
        for (i=1;i<=n;i++){
            cin>>b[i];
            if (b[i] > a[i] || !f[b[i]])
                ok = 0;
        }
        for (i=1;i<=m;i++){
            cin>>x>>y;
            L[x].push_back(y);
            L[y].push_back(x);

            /// fac update in aint cu intervalul pt muchia asta
            update_aint (1,1,n,max(b[x],b[y]),min(a[x],a[y]),x,y);

        }

        if (!ok){
            cout<<0<<"\n";
            continue;
        }

        if (n == 1 && !m){
            if (a[1] == b[1])
                cout<<"1\n";
            else cout<<"0\n";
            continue;
        }

        if (n == 2 && m == 1){
            if ( (a[1] == b[1] && a[2] == b[2]) || (min (a[1],a[2]) == b[1] && min (a[1],a[2]) == b[2]) )
                cout<<"1\n";
            else cout<<"0\n";
            continue;
        }

        /// graf stea
        int nod = 0, cnt = 0;
        for (i=1;i<=n;i++){
            if (L[i].size() == 1)
                cnt++;
            else nod = i;
        }
        if (cnt == n-1){

            int maxi = 0, mini = n+1;
            for (i=1;i<=n;i++){
                if (b[i] == a[i])
                    continue;

                maxi = max (maxi,b[i]);
                if (i != nod)
                    mini = min (mini,b[i]);
            }
            if (maxi && (maxi > a[nod] || mini < b[nod])){
                cout<<"0\n";
                continue;
            }
            /// acum sa vad daca exista b[nod]
            int ok = 0;
            if (!maxi)
                ok = 1;
            for (i=1;i<=n;i++)
                if (i != nod && b[i] == b[nod]){
                    ok = 1;
                    break;
                }
            cout<<ok<<"\n";

            continue;
        }

        /// graf complet
        if (m == 1LL*n*(n-1)/2){

            cout<<1<<"\n";
            continue;
        }

        /// lant
        int start = 0;
        cnt = 0;
        for (i=1;i<=n;i++)
            if (L[i].size() == 1){
                if (!start)
                    start = i;
                cnt++;
            }

        if (cnt == 2 && m == n-1){
            memset (viz,0,sizeof viz); k = 0;
            dfs (start);

            if (solve (v,k))
                cout<<"1\n";
            else cout<<"0\n";

            continue;
        }

        /// arbore

        if (1LL*n*n <= 5000000){
            for (i=1;i<=n;i++){
                if (a[i] == b[i])
                    continue;
                for (j=1;j<=n;j++)
                    viz[j] = 0;
                g = 0;
                dfs2 (i);
                if (!g)
                    break;
            }
            if (i > n)
                cout<<"1\n";
            else cout<<"0\n";

            continue;
        }

        /// permutarea
        if (m == n-1){
            k = 0;
            dfs3 (1,0);

            for (i=1;i<=k;i++)
                rmq[0][i] = make_pair(level[E[i]],i);

            for (i=1;(1<<i)<=k;i++)
                for (j=1;j<=k;j++){
                    rmq[i][j] = rmq[i-1][j];
                    if (j + (1<<(i-1)) <= k && rmq[i-1][j + (1<<(i-1))].first < rmq[i][j].first)
                        rmq[i][j] = rmq[i-1][j + (1<<(i-1))];
                }

            for (i=2;i<=k;i++)
                p[i] = p[i/2] + 1;


            for (j=1;(1<<j)<=n;j++)
                for (i=1;i<=n;i++){
                    dp[i][j].nod = dp[dp[i][j-1].nod][j-1].nod;
                    dp[i][j].minia = min (dp[i][j-1].minia, dp[ dp[i][j-1].nod ][j-1].minia);
                    dp[i][j].maxib = max (dp[i][j-1].maxib, dp[ dp[i][j-1].nod ][j-1].maxib);
                }

            for (i=1;i<=n;i++)
                idx[a[i]] = i;

            for (i=1;i<=n;i++){
                if (a[i] == b[i])
                    continue;

                mini = INF, maxi = -INF;
                solve2 (idx[b[i]],i);

                if (mini < b[i] || maxi > b[i])
                    break;

            }
            if (i > n)
                cout<<"1\n";
            else cout<<"0\n";

            continue;
        }

        /// de aici devine interesant

        for (i=1;i<=n;i++){
            poz_a[a[i]].push_back(i);
            poz_b[b[i]].push_back(i);
            fth[i] = i;
        }
        memset (Size,1,sizeof Size);

        sol_final = 1;
        query_aint (1,1,n);

        cout<<sol_final<<"\n";
    }

    return 0;
}


Compilation message

colors.cpp: In function 'void unite(int, int)':
colors.cpp:170:5: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
     if (Size[radx] < Size[rady]);
     ^~
colors.cpp:171:9: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
         swap (radx,rady);
         ^~~~
# 결과 실행 시간 메모리 Grader output
1 Correct 201 ms 78840 KB Output is correct
2 Correct 101 ms 78584 KB Output is correct
3 Correct 51 ms 78208 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 218 ms 78968 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 413 ms 79992 KB Output is correct
2 Correct 124 ms 79608 KB Output is correct
3 Correct 54 ms 79352 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 413 ms 79992 KB Output is correct
2 Correct 124 ms 79608 KB Output is correct
3 Correct 54 ms 79352 KB Output is correct
4 Correct 661 ms 79992 KB Output is correct
5 Correct 789 ms 98300 KB Output is correct
6 Correct 1159 ms 126672 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 201 ms 78840 KB Output is correct
2 Correct 101 ms 78584 KB Output is correct
3 Correct 51 ms 78208 KB Output is correct
4 Correct 413 ms 79992 KB Output is correct
5 Correct 124 ms 79608 KB Output is correct
6 Correct 54 ms 79352 KB Output is correct
7 Correct 252 ms 80016 KB Output is correct
8 Correct 129 ms 79736 KB Output is correct
9 Correct 96 ms 78204 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 450 ms 79992 KB Output is correct
2 Correct 850 ms 125508 KB Output is correct
3 Correct 1028 ms 199916 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 143 ms 79480 KB Output is correct
2 Correct 86 ms 78584 KB Output is correct
3 Correct 98 ms 78200 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 201 ms 78840 KB Output is correct
2 Correct 101 ms 78584 KB Output is correct
3 Correct 51 ms 78208 KB Output is correct
4 Correct 218 ms 78968 KB Output is correct
5 Correct 413 ms 79992 KB Output is correct
6 Correct 124 ms 79608 KB Output is correct
7 Correct 54 ms 79352 KB Output is correct
8 Correct 661 ms 79992 KB Output is correct
9 Correct 789 ms 98300 KB Output is correct
10 Correct 1159 ms 126672 KB Output is correct
11 Correct 252 ms 80016 KB Output is correct
12 Correct 129 ms 79736 KB Output is correct
13 Correct 96 ms 78204 KB Output is correct
14 Correct 450 ms 79992 KB Output is correct
15 Correct 850 ms 125508 KB Output is correct
16 Correct 1028 ms 199916 KB Output is correct
17 Correct 143 ms 79480 KB Output is correct
18 Correct 86 ms 78584 KB Output is correct
19 Correct 98 ms 78200 KB Output is correct
20 Correct 358 ms 78720 KB Output is correct
21 Execution timed out 3077 ms 86928 KB Time limit exceeded
22 Halted 0 ms 0 KB -