wc2013 糖果公园

传送门:http://uoj.ac/problem/58
思路:果断树上莫队模板,果断看的题解,,关于时间作为第三维推来推去idea还是极好的,弄了好久就因为不明白出战入站序的性质,,,反省,而且被vfk讲晕了,,明显他的集合标准差是另一种直接在树上做的写法,还是出战入站序好用,,,本来狂WA不止,,原来是没开LL,改了还是WA,,睡了,,第二天微机课,,改了快的大小,,仍然WA,不得已看了标程,,然而,,,就把一个内容改写成了函数,,就A了,,,什么玩意,,我明明没动程序好吧,,,就是不明白啊,,,貌似还有块状树的做法,有些部分分的做法也是值得借鉴的,,,
未完待续(非常重要)
代码:

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define N 100000
using namespace std;
typedef long long LL;
struct edge{ int nxt,point,v;};
struct node { int t,x,y,id; LL ans;};
struct data{ int num,last,now;};
edge e[(N<<1)+5];
node que1[(N<<1)+5];
data que2[(N<<1)+5];
int n,m,q,cnt,cnt1,cnt2,time1;
int v[N+5],w[N+5],a[N+5],b[N+5],dfn[(N<<1)+5],l[N+5],r[N+5],fa[N+5][25],deep[N+5],pos[(N<<1)+5],ts[N+5];
bool vis[N+5];
LL sum;
inline void addedge(int u1,int v1){
  e[++cnt].nxt = e[u1].point; e[u1].point = cnt; e[cnt].v = v1;} 
inline void insert(int u1,int v1){ addedge(u1,v1); addedge(v1,u1);}
inline bool cmp(node a,node b){ 
  return ((pos[a.x] < pos[b.x])||(pos[a.x] == pos[b.x]&&pos[a.y]<pos[b.y])||
  (pos[a.x] == pos[b.x]&&pos[a.y] == pos[b.y]&&a.t < b.t));}
inline bool cmp1(node a,node b){ return (a.id < b.id);}
inline int getnum(){
    char c; int num;
    while (!isdigit(c = getchar()));
    num = c - '0';
    while (isdigit(c = getchar())) num = 10 * num + c - '0';
    return num;
}

void init(){
    n = getnum(); m = getnum(); q = getnum(); cnt = 0;
    for (int i = 1;i <= m; ++i) v[i] = getnum();
    for (int i = 1;i <= n; ++i) w[i] = getnum();
    for (int i = 1;i < n; ++i){
       int u1 = getnum(),v1 = getnum();
       insert(u1,v1);   
    } 
    for (int i = 1;i <= n; ++i) a[i] = b[i] = getnum();
    time1 = 0;
}

inline void dfs(int x){
    l[x] = ++time1; dfn[time1] = x; 
    for (int i = 1;i <= 20; ++i) fa[x][i] = fa[fa[x][i-1]][i-1];
    for (int p = e[x].point;p; p = e[p].nxt)
      if (!l[e[p].v]) {
      deep[e[p].v] = deep[x] + 1; fa[e[p].v][0] = x;
      dfs(e[p].v);}
    r[x] = ++time1; dfn[time1] = x;
}

inline int LCA(int u,int v){
    if (deep[u] < deep[v]) swap(u,v);
    int ll = deep[u] - deep[v];
    for (int i = 20;i >= 0; --i)
      if (ll&(1<<i)) u = fa[u][i];
    for (int i = 20;i >=0; --i)
      if (fa[u][i] != fa[v][i]) u = fa[u][i],v = fa[v][i];
    if (u != v) return fa[u][0];
    return u; 
}

void sort_it(){
    int sz = (int)pow(time1, 2.0 / 3.0);
    for (int i = 1;i <= time1; ++i) pos[i] = i/sz; 
    bool p;
    int u1,v1;
    cnt1 = cnt2 = 0;
    for (int i = 1;i <= q; ++i){
        p = getnum(); u1 = getnum(); v1 = getnum();
        if (!p) que2[++cnt2].num = u1,que2[cnt2].last = b[u1],que2[cnt2].now = b[u1] = v1;
        else{ int lca = LCA(u1,v1);
        if (l[u1] > l[v1]) swap(u1,v1);
              que1[++cnt1].t = cnt2;
              que1[cnt1].id = cnt1;
              if (lca != u1) que1[cnt1].x = r[u1], que1[cnt1].y = l[v1];
              else que1[cnt1].x = l[u1],que1[cnt1].y = l[v1];}
    }
    sort(que1 + 1,que1 + cnt1 + 1,cmp); 
//  for (int i = 1;i <= cnt1; ++i) cout<<que1[i].id<<endl;
} 

inline void change(int x){
    if (vis[x]) sum = sum -  (LL)v[a[x]]*w[ts[a[x]]--]; 
    else sum = sum + (LL)v[a[x]]*w[++ts[a[x]]];
    vis[x] ^= 1; 
}

inline void modify(int s,int f){
      if (vis[s])
    {
        change(s);
        a[s] = f;
        change(s);
    }
    else a[s] = f;
}

inline void change_time(int i){
    for (int j = que1[i-1].t + 1;j <= que1[i].t; ++j) modify(que2[j].num,que2[j].now);
    for (int j = que1[i-1].t ;j > que1[i].t; --j) modify(que2[j].num,que2[j].last);
} 

void make_it(){
    memset(vis,0,sizeof(vis));
    memset(ts,0,sizeof(ts));
    //for (int i = 1;i <= n; ++i) ts[a[i]] ++; 
    que1[0].t = 0; que1[0].x = 1; que1[0].y = 0; sum = 0;
    for (int i = 1;i <= cnt1; ++i){
        change_time(i);
        //cout<<sum<<endl;
        for (int j = que1[i-1].x - 1;j >= que1[i].x; --j) change(dfn[j]);
            //for (int j = 1;j <= n; ++j) cout<<vis[j]<<" "; cout<<endl; 
        for (int j = que1[i-1].y + 1;j <= que1[i].y; ++j) change(dfn[j]);
            //cout<<sum<<endl;
            //for (int j = 1;j <= n; ++j) cout<<vis[j]<<" ";cout<<endl; 
        for (int j = que1[i-1].x;j < que1[i].x; ++j) change(dfn[j]);
            //for (int j = 1;j <= n; ++j) cout<<vis[j]<<" ";cout<<endl; 
        for (int j = que1[i-1].y;j > que1[i].y; --j) change(dfn[j]);
            //for (int j = 1;j <= n; ++j) cout<<vis[j]<<" ";cout<<endl; 
        //for (int j = 1;j <= n; ++j) cout<<vis[j]<<" ";
        //cout<<endl; 
        //cout<<sum<<" ";
        int u = dfn[que1[i].x],v = dfn[que1[i].y],lca = LCA(u,v);
        if (u != lca && v != lca) change(lca);
        que1[i].ans = sum;
        //cout<<sum<<endl;
        if (u != lca && v != lca) change(lca); 
    }
}

void DO_IT(){
    dfs(1);
    //for (int i = 1;i <= time; ++i) cout<<dfn[i]<<endl;
    sort_it();
    //for (int i = 1;i <= cnt1; ++i) cout<<que1[i].x<<" "<<que1[i].y<<" "<<que1[i].t<<" "<<endl;
    make_it();
}

void print(){
    sort(que1 + 1,que1 + cnt1 + 1,cmp1);
    for (int i = 1;i <= cnt1; ++i) printf("%lld\n",que1[i].ans);
}

int main(){
    init();
    DO_IT();
    print();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值