• 个人简介

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    struct node{
        int x, y, z, w;
    }sum[200005];
    int n, idx, a[200005], b[200005], q, p, c, cnt, cntb, low[200005], dfn[200005], vis[200005];
    stack<int> st;
    vector<pair<int, int> > g[200005];
    int co[200005], res[200005];
    void tarjan(int u){
        cnt++;
        dfn[u]=low[u]=cnt;
        st.push(u);
        vis[u]=1;
        for(int i=0;i<vc[u].size();i++){
            int to=vc[u][i];
            if(dfn[to]==0){
                tarjan(to);
                low[u]=min(low[u], low[to]);
            }else if(vis[u]==1){
                low[u]=min(low[u], dfn[to]);
            }
        }
        if(dfn[u]==low[u]){
            int id;
            cntb++;
            vector<int> v;
            do{
                id=st.top();
                st.pop();
                vis[id]=0;
                co[id]=cntb;
                v.push_back(id);
            }while(id!=u);
            int ww=0;
            for(int i=v.size()-1;i>=0;i--){
                g[cntb].push_back({v[i], 0});
                res[v[i]]=ww;
                ww++;
            }
        }
    }
    int fpow(int a, int b){
        int ans=1;
        while(b){
            if(b%2==1)ans=ans*a%mod;
            a=a*a%mod;
            b/=2;
        }
        return ans;
    }
    int nxt[200005], in[200005], num[200005], en[200005];
    //sum中对应的编号 末尾的环的tarjan上的编号 剩余长度 当前消耗了多少长度
    int get(int )
    signed main(){
        cin >> n;
        for(int i=1;i<=n;i++){
            cin >> a[i];
        }
        for(int i=1;i<=n;i++){
            int x;
            cin >> x;
            vc[i].push_back(x);
        }
        for(int i=1;i<=n;i++){
            tarjan(i);
        }
        for(int i=1;i<=n;i++){
            for(int j=0;j<vc[i].size();i++){
                int to=vc[i][j];
                if(co[i]!=co[to]){
                    nxt[co[i]]=nxt[co[to]];
                    in[co[to]]++;
                }
            }
        }
        for(int i=1;i<=cntb;i++){
            if(in[i]!=0)continue;
            int tot=0, lst=0;
            for(int j=i;j;j=nxt[j]){
                tot++;
                int u=j;
                for(int k=0;k<g[u].size();k++){
                    lst=j;
                    idx++;
                    g[u][k].second=idx;
                    int v=g[u][k].first;
                    sum[idx].x=num*a[v];
                    sum[idx].y=2*a[v];
                    sum[idx].z=a[v];
                    sum[idx].w=a[v]*a[v];
                    if(nxt[j]!=0&&j!=i){
                        sum[idx].x+=sum[idx-1].x;
                        sum[idx].y+=sum[idx-1].y;
                        sum[idx].z+=sum[idx-1].z;
                        sum[idx].w+=sum[idx-1].w;
                    }else if(nxt[j]==0&&k!=0){
                        sum[idx].x+=sum[idx-1].x;
                        sum[idx].y+=sum[idx-1].y;
                        sum[idx].z+=sum[idx-1].z;
                        sum[idx].w+=sum[idx-1].w;
                    }
                }
            }
            for(int j=i;j;j=nxt[j]){
                num[j]=tot;
                en[j]=lst;
            }
        }
        cin >> q;
        while(q--){
            cin >> p >> c;
            int id=co[p], ans=0;
            ans=n*(n-1)%mod*(2*n%mod-1)%mod*fpow(6, mod-2)%mod;
            if(vc[id].size()==1){
                idx=g[id][0].second;
                if(num[id]>c){
                    ans+=sum[idx+c-1].w+2*sum[idx+c-1].x;
                }else{
                    ans+=sum[idx+num[id]-2].w+2*sum[idx+num[id]-2].x;
                    ans+=get(idx+num[id]-1, en[id], c-num[id]+1, num[id]-1);
                    //sum中对应的编号 末尾的环的tarjan上的编号 剩余长度 当前消耗了多少长度
                }
            }else{
                idx=g[id][res[p]].second;
                if(res[p]==0){
                    ans+=get(idx, id, c, 0);
                }else{
                    int end=idx+g[id].size()-1-res[p];
                    ans+=get(g[id][0].first, id, c-(end-res[p]+1), end-res[p]+1);
                    ans+=2*(sum[end].x-sum[idx-1].x)-res[p]*(sum[end].z-sum[idx-1].z)+sum[end].w-sum[idx-1].w;
                }
            }
            cout << ans <<endl;
        }
        return 0;
    }
    /*
    (ax+j)^2=ax^2+2*ax*j+j^2;
    j^2=n*(n+1)*(2*n+1)/6;
    缩点找出所有的环
    然后按照点唯一的走法分出不同的链 但其实用一个数组存就够了
    每条链都必然走向一个环 环之前的部分可以预处理出ax^2+2*ax*j的贡献
    环上的点的贡献ax^2
    设环上点的顺序编号为id len为环长 num=c/len
    则这个点的贡献为a[i]*(id*num+2*num*(num-1))
    求一个环上的前缀和分别为  a[i]*id  a[i]*2  a[i]
    
    */
    
  • 通过的题目

  • 最近活动

  • 最近编写的题解

    This person is lazy and didn't write any solutions.

题目标签

入门组模拟
2
高精度
1
语言基础
1
字符串、字符数组
1