제출 #892772

#제출 시각아이디문제언어결과실행 시간메모리
892772alexander707070Tourism (JOI23_tourism)C++14
100 / 100
4524 ms48668 KiB
#include<bits/stdc++.h>
#pragma GCC optimize ("O3")
#pragma GCC target ("sse4")
#define MAXN 100007
using namespace std;

const int bucket_sz=500;

struct qr{
    int l,r,id;
}qs[MAXN];

struct node{
    int l,r;
}w[MAXN];

struct event{
    int type,ind,val,tim;
};

stack<event> st;

int n,m,q,a,b,tt,dist[MAXN],bucket[MAXN],l,r,cnt[MAXN],tim,sum,last,ans[MAXN];
int c[MAXN],num[MAXN],ret[MAXN],fr[MAXN];
vector<int> v[MAXN],euler;

void dfs(int x,int p,int d){
    tt++; num[x]=tt; ret[tt]=x;
    dist[x]=d;

    fr[x]=int(euler.size());
    euler.push_back(num[x]);

    for(int i=0;i<v[x].size();i++){
        if(v[x][i]==p)continue;
        dfs(v[x][i],x,d+1);

        euler.push_back(num[x]);
    }
}

bool li[4*MAXN][20];
int dp[4*MAXN][20];

int lg[4*MAXN],power[20];

void calc(){
    power[0]=1;
    for(int i=1;i<20;i++)power[i]=power[i-1]*2;
    lg[1]=0;
    for(int i=2;i<=4*n;i++)lg[i]=lg[i/2]+1;
}

int rmq(int i,int j){
    if(j==0)return euler[i];

    if(li[i][j])return dp[i][j];
    li[i][j]=true;

    dp[i][j]=min( rmq(i,j-1) , rmq(i+power[j-1],j-1) );
    return dp[i][j];
}

int lca(int x,int y){
    if(fr[x]>fr[y])swap(x,y);
    x=fr[x]; y=fr[y];

    return ret[ min( rmq(x,lg[y-x+1]) , rmq(y-power[lg[y-x+1]]+1,lg[y-x+1]) ) ];
}

int distance(int x,int y){
    if(x==0 or y==n+1)return 0;

    return dist[x]+dist[y]-2*dist[lca(x,y)];
}

bool cmp(qr fr,qr sc){
    if(bucket[fr.l]!=bucket[sc.l])return bucket[fr.l]<bucket[sc.l];
    if(fr.r!=sc.r)return fr.r>sc.r;   
    return fr.l<sc.l;
}

void insertv(int x,int y,int z){
    sum-=distance(ret[y],ret[z]);
    sum+=distance(ret[y],ret[x]);
    sum+=distance(ret[x],ret[z]);

    w[x].l=y; w[x].r=z;
    w[y].r=x; w[z].l=x;
}

void erasev(int x){
    st.push({1,w[x].l,x,tim});
    st.push({2,w[x].r,x,tim});

    w[w[x].l].r=w[x].r;
    w[w[x].r].l=w[x].l;
}

void rem(int x){
    if(x==0){
        tim++; return;
    }

    tim++;
    x=num[c[x]];
    cnt[x]--;

    if(cnt[x]!=0)return;

    st.push({3,0,sum,tim});

    sum-=distance(ret[w[x].l],ret[x]);
    sum-=distance(ret[x],ret[w[x].r]);
    sum+=distance(ret[w[x].l],ret[w[x].r]);

    erasev(x);
}

void undo(){
    while(!st.empty() and st.top().tim==tim){
        if(st.top().type==1){
            w[st.top().ind].r=st.top().val;
        }
        if(st.top().type==2){
            w[st.top().ind].l=st.top().val;
        }
        if(st.top().type==3){
            sum=st.top().val;
        }

        st.pop();
    }
    tim--;
}

void reset(){
    tim=sum=0;
    while(!st.empty())st.pop();
    for(int i=1;i<=n;i++)cnt[i]=0;
}

int edge(){
    int lx=w[0].r,rx=w[n+1].l;
    return distance(ret[lx],ret[rx]);
}

int main(){

    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    cin>>n>>m>>q;
    calc();

    for(int i=1;i<=n-1;i++){
        cin>>a>>b;
        v[a].push_back(b);
        v[b].push_back(a);
    }
    dfs(1,0,0);

    w[0].l=n+1;
    w[n+1].r=0;
    ret[n+1]=n+1;

    for(int i=1;i<=m;i++){
        cin>>c[i];
        bucket[i]=i/bucket_sz;
    }

    for(int i=1;i<=q;i++){
        cin>>qs[i].l>>qs[i].r;
        qs[i].id=i;
    }

    sort(qs+1,qs+q+1,cmp);

    for(int i=1;i<=q;i++){
        if(i==1 or bucket[qs[i].l]!=bucket[qs[i-1].l]){
            reset();
            for(int f=bucket[qs[i].l]*bucket_sz;f<=m;f++){
                cnt[num[c[f]]]++;
            }

            last=0;
            for(int f=1;f<=n;f++){
                if(cnt[f]==0)continue;
                insertv(f,last,n+1);
                last=f;
            }
            l=bucket[qs[i].l]*bucket_sz;
            r=m;
        }

        while(r>qs[i].r){
            rem(r); r--;
        }

        while(l<qs[i].l){
            rem(l); l++;
        }

        ans[qs[i].id]=(sum+edge())/2;

        if(qs[i+1].r==qs[i].r and qs[i+1].l>=qs[i].l and bucket[qs[i+1].l]==bucket[qs[i].l]){
            continue;
        }

        while(l>bucket[qs[i].l]*bucket_sz){
            undo(); l--; cnt[num[c[l]]]++;
        }

    }

    for(int i=1;i<=q;i++){
        cout<<ans[i]+1<<"\n";
    }

    return 0;
}

컴파일 시 표준 에러 (stderr) 메시지

tourism.cpp: In function 'void dfs(int, int, int)':
tourism.cpp:34:18: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   34 |     for(int i=0;i<v[x].size();i++){
      |                 ~^~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...