absi2011's Blog & Daily Life.

全新的开始       我要省选翻盘       I wanna AK in 高考\化学       自此,生无可恋
[破碎的状态] [-38] 100818 B
[破碎的状态] [-37] 100818 E

[破碎的状态] [-37] 100818 B-分块解法

absi2011 posted @ Jun 15, 2016 10:17:22 AM in 刷题记录 with tags LCA CF Gym 分块 瞎搞 小高考 , 597 阅读

总觉得之前是非正解

这个写出来以后发现..更非正解..

题意:http://absi2011.is-programmer.com/posts/202346.html

记b(i)表示到i到根的路径的权值和..

每次修改就是一段区间的修改..

然后..我们就可以愉快的玩差分了...

然后分块处理..复杂度是[tex]O(kq + q\sqrt{n})[/tex]的

但是..不知道为啥跑得比之前那个慢多了..

不管了..就这样吧

代码:

#include<set>
#include<map>
#include<list>
#include<queue>
#include<stack>
#include<math.h>
#include<string>
#include<time.h>
#include<bitset>
#include<vector>
#include<memory>
#include<utility>
#include<stdio.h>
#include<sstream>
#include<fstream>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct edge
{
    int y;
    edge * next;
};
edge * li[500005];
edge * new_edge()
{
    static edge a[1000005];
    static int top=0;
    return &a[top++];
}
void inserts(int x,int y)
{
    edge * t=new_edge();
    t->y=y;
    t->next=li[x];
    li[x]=t;
}
void insert_edge(int x,int y)
{
    inserts(x,y);
    inserts(y,x);
}
int dfn[500005];
long long a[500005];
long long sum[500005];
int block=735;
int father[500005];
int depth[500005];
int size[500005];
long long b[500005];
void dfs(int x)
{
    static int now=0;
    dfn[x]=now++;
    edge * t;
    size[x]=1;
    for (t=li[x];t!=0;t=t->next)
    {
        if (t->y==father[x]) continue;
        father[t->y]=x;
        depth[t->y]=depth[x]+1;
        dfs(t->y);
        size[x]+=size[t->y];
    }
}
int n;
int up[500005][25];
void get_lca()
{
    int i;
    for (i=0;i<n;i++)
    {
        up[i][0]=father[i];
    }
    for (i=1;i<20;i++)
    {
        int j;
        for (j=0;j<n;j++)
        {
            if (up[j][i-1]==-1)
            {
                up[j][i]=-1;
            }
            else
            {
                up[j][i]=up[up[j][i-1]][i-1];
            }
        }
    }
}
int lca(int x,int y)
{
    if (depth[x]<depth[y]) swap(x,y);
    int t=depth[x]-depth[y];
    int i;
    for (i=19;i>=0;i--)
    {
        if ((1<<i)&t) x=up[x][i];
    }
    if (x==y) return x;
    for (i=19;i>=0;i--)
    {
        if (up[x][i]==up[y][i]) continue;
        x=up[x][i];
        y=up[y][i];
    }
    return father[x];
}
long long calc_ans(int x)
{
    int i=0;
    long long ans=0;
    int j=0;
    for (;;)
    {
        i+=block;
        if (i>x) break;
        ans+=sum[j];
        j++;
    }
    i-=block;
    for (;i<=x;i++) ans+=a[i];
    return ans;
}
int main()
{
    #ifdef absi2011
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    #endif
    ios::sync_with_stdio(false);
    scanf("%d",&n);
    int i;
    for (i=1;i<n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        insert_edge(x,y);
    }
    father[0]=0;
    depth[0]=0;
    dfs(0);
    get_lca();
    for (i=0;i<n;i++)
    {
        int x;
        scanf("%d",&x);
        b[i]=x;
        a[dfn[i]]=x;
        sum[dfn[i]/block]+=x;
        a[dfn[i]+size[i]]-=x;
        sum[(dfn[i]+size[i])/block]-=x;
    }
    int m;
    scanf("%d",&m);
    for (i=0;i<m;i++)
    {
        int k;
        scanf("%d",&k);
        int j;
        int x1,y1,aa,bb,cc,dd;
        scanf("%d%d%d%d%d%d",&x1,&y1,&aa,&bb,&cc,&dd);
        for (j=0;j<k;j++)
        {
            if (x1<n)
            {
                b[x1]+=y1;
                a[dfn[x1]]+=y1;
                sum[dfn[x1]/block]+=y1;
                a[dfn[x1]+size[x1]]-=y1;
                sum[(dfn[x1]+size[x1])/block]-=y1;
            }
            x1=((long long)x1*aa+bb)%n;
            y1=((long long)y1*cc+dd)%1000000007;
        }
        long long ans=0;
        int x,y;
        scanf("%d%d",&x,&y);
        ans=calc_ans(dfn[x])+calc_ans(dfn[y])-2*calc_ans(dfn[lca(x,y)])+b[lca(x,y)];
        cout<<ans<<'\n';
    }
    return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter