• codeforces840E In a Trap


    好巧妙啊,感觉从来没有用过按位dp的trick,也没有用过树上链分块的trick

    挂个,全程看他的思路写的,当然lych帮我理解了最难懂的一部分

    首先这里有个玄学的分块

    每个点统计它上面256(其实差不多就是n^0.5)个点的情况

    但是发现不同的块需要不同的处理,因为不同的块在第9位及以上的位会产生影响

    所以对于每个点都需要预处理出Fi,也就是当这个块是统计答案时的第i个块时的最大答案

    那么在跳的时候只要疯狂的跳256,同时记录下当前这一块已经是统计的第几块,最后不到256个暴力判一下

    然而

    暴力预处理是n*(256)^2≈n^2的

    gg

    于是可以用一个类似dp的方法做出来

    首先把每一个答案找一个最好的地方放好(就是块内的每一个点所对应的答案找一个i使答案的9~16位为11111111)

    接下来就一定是这些答案通过与下标同异或一个东西所得到的答案了

    先枚举位,考虑这些dp值在这一位取反对答案的贡献

    没了(感性理解是对的)

     1 #include <bits/stdc++.h>
     2 #define KUAI 256
     3 #define LOG 8
     4 #define FULL 255
     5 using namespace std;
     6 int n,m,E,x,y;
     7 int dep[50001],fa[50001],Fa[50001],ans[50001][300],a[50001],fir[50001],nex[100001],to[100001];
     8 void add(int x,int y)
     9 {
    10     nex[++E]=fir[x];fir[x]=E;to[E]=y;
    11 }
    12 void build(int now,int fat)
    13 {
    14     if(now==5)
    15         int e=1;
    16     dep[now]=dep[fat]+1;
    17     fa[now]=fat;
    18     for(int i=0,x=now;i<=KUAI && x;i++,x=fa[x])
    19     if(i==KUAI)
    20         Fa[now]=x;
    21     else
    22     {
    23         int y=a[x]^i;//当前答案 
    24         ans[now][FULL^(y>>LOG)]=max(ans[now][FULL^(y>>LOG)],y|(FULL<<LOG));//在最好的地方放好 
    25     } 
    26     for(int i=0;i<LOG;i++)
    27         for(int j=0;j<KUAI;j++)
    28             if(ans[now][j]==0)
    29             if(ans[now][j^(1<<i)])
    30                 ans[now][j]=ans[now][j^(1<<i)]^(1<<(LOG+i));
    31     for(int i=fir[now];i;i=nex[i])
    32     if(to[i]!=fa[now])
    33         build(to[i],now);
    34 }
    35 int main()
    36 {
    37     scanf("%d%d",&n,&m);
    38     for(int i=1;i<=n;i++)
    39         scanf("%d",&a[i]);
    40     for(int i=1;i<n;i++)
    41         scanf("%d%d",&x,&y),
    42         add(x,y),add(y,x);
    43     build(1,0);
    44     for(int i=1;i<=m;i++)
    45     {
    46         scanf("%d%d",&x,&y);
    47         if(i==2)
    48             int e=1;
    49         swap(x,y);
    50         int ret=a[y]^(dep[x]-dep[y]),j=0,de=0;
    51         for(;dep[x]-dep[y]>=KUAI;j++,de+=KUAI)
    52             ret=max(ret,ans[x][j]),x=Fa[x];
    53         for(;x!=y;x=fa[x],de++)
    54             ret=max(ret,a[x]^de);
    55         printf("%d
    ",ret);
    56     }
    57     return 0;
    58 }
  • 相关阅读:
    poj 3026 Borg Maze
    poj2828 Buy Tickets
    poj3264 Balanced Lineup
    高精度运算
    poj1035 Spell checker
    poj2318 TOYS 点积叉积理解
    求两直线交点的一般做法
    C语言I博客作业05
    C语言I博客作业04
    C语言I博客作业07
  • 原文地址:https://www.cnblogs.com/wanglichao/p/7429683.html
Copyright © 2020-2023  润新知