洛谷P3603 || bzoj 4763 雪辉 && bzoj4812: [Ynoi2017]由乃打扑克

https://www.luogu.org/problemnew/show/P3603

https://www.lydsy.com/JudgeOnline/problem.php?id=4763

就是先树分块,取所有的块顶为关键点

那么任意点与它祖先中离它最近的关键点的距离为根号级别

先预处理出任意两个关键点之间的路径上有的值的bitset

(vv[i][j][k]表示i到j的路径上是否出现值k)

那么,只需要在询问时,对于路径(a,b),得到它路径上有的值的bitset;对于每个询问,把所有得到的bitset或一下就行了

得到bitset的方法见代码。。。

复杂度:n*(sqrt(n)+30000/32)

以下代码常数超大!为了卡常特意手写了bitset,还把块大小改到550(不是根号,实测这样更快...)

貌似有别的方法重建树的,常数小得多了

  1 #pragma GCC optimize(3)
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<vector>
  6 #include<bitset>
  7 using namespace std;
  8 #define fi first
  9 #define se second
 10 #define mp make_pair
 11 #define pb push_back
 12 typedef long long ll;
 13 typedef unsigned long long ull;
 14 typedef pair<int,int> pii;
 15 int n,m,F;
 16 vector<int> e[100100];
 17 int dd[100100];
 18 const int bsz=480;
 19 ull lft[64];
 20 void init()
 21 {
 22     lft[0]=1;
 23     for(int i=1;i<64;i++)    lft[i]=lft[i-1]<<1;
 24 }
 25 struct bs
 26 {
 27 ull d[bsz];
 28 int _Find_first_zero()
 29 {
 30     for(int i=0;i<bsz;i++)
 31         if(d[i]!=0xffffffffffffffff)
 32             return (i<<6)+__builtin_ffsll(~d[i])-1;
 33 }
 34 void reset()
 35 {
 36     for(int i=0;i<bsz;i++)    d[i]=0;
 37 }
 38 void set(int p,bool q=1)
 39 {
 40     if(q)    d[p>>6]|=lft[p-((p>>6)<<6)];
 41     else    d[p>>6]&=~lft[p-((p>>6)<<6)];
 42 }
 43 int count()
 44 {
 45     int ans=0;
 46     for(int i=0;i<bsz;i++)    ans+=__builtin_popcountll(d[i]);
 47     return ans;
 48 }
 49 bs &operator|=(const bs &b)
 50 {
 51     for(int i=0;i<bsz;i++)    d[i]|=b.d[i];
 52     return *this;
 53 }
 54 };
 55 int bl[100100],rt[310],cnt;
 56 const int sz=550;
 57 namespace GBLOCK
 58 {
 59 int st[100100],tp;
 60 void dfs(int u,int fa)
 61 {
 62     int i,ltp=tp;
 63     for(i=0;i<e[u].size();i++)
 64         if(e[u][i]!=fa)
 65         {
 66             dfs(e[u][i],u);
 67             if(tp-ltp>=sz)
 68             {
 69                 rt[++cnt]=u;
 70                 while(tp!=ltp)    bl[st[tp--]]=cnt;
 71             }
 72         }
 73     st[++tp]=u;
 74 }
 75 void work()
 76 {
 77     dfs(1,0);
 78     ++cnt;rt[cnt]=1;
 79     while(tp)    bl[st[tp--]]=cnt;
 80 }
 81 }
 82 namespace LCA
 83 {
 84 int anc[100100][20],dep[100100],l2n=19;
 85 void dfs(int u,int fa)
 86 {
 87     int i;
 88     anc[u][0]=fa;
 89     dep[u]=dep[fa]+1;
 90     for(i=1;i<=l2n;i++)
 91         anc[u][i]=anc[anc[u][i-1]][i-1];
 92     for(i=0;i<e[u].size();i++)
 93         if(e[u][i]!=fa)
 94             dfs(e[u][i],u);
 95 }
 96 int lca(int x,int y)
 97 {
 98     int t,i;
 99     if(dep[x]<dep[y]){t=x;x=y;y=t;}
100     for(t=dep[x]-dep[y],i=0;t>0;t>>=1,i++)
101         if(t&1)    x=anc[x][i];
102     if(x==y)    return x;
103     for(i=l2n;i>=0;i--)
104         if(anc[x][i]!=anc[y][i])
105         {
106             x=anc[x][i];
107             y=anc[y][i];
108         }
109     return anc[x][0];
110 }
111 }
112 using LCA::lca;
113 using LCA::dep;
114 using LCA::anc;
115 int nn[100100],nnn;
116 bs vv[310][310];//vv[i][j]:rt[i],rt[j]间答案
117 int num[30100];bs vis;
118 namespace PRE
119 {
120 int s;
121 void dfs(int u,int fa)
122 {
123     int i;
124     if(!num[dd[u]])    vis.set(dd[u]);
125     ++num[dd[u]];
126     if(nn[u])    vv[s][nn[u]]=vis;
127     for(i=0;i<e[u].size();i++)
128         if(e[u][i]!=fa)
129             dfs(e[u][i],u);
130     --num[dd[u]];
131     if(!num[dd[u]])    vis.set(dd[u],0);
132 }
133 void work()
134 {
135     int i;
136     for(i=1;i<=cnt;i++)
137         if(!nn[rt[i]])
138             nn[rt[i]]=++nnn;
139     for(i=1;i<=n;i++)
140         if(nn[i])
141         {
142             s=nn[i];
143             dfs(i,0);
144         }
145 }
146 }
147 bs tt;
148 void jump1(int &x,int ed)
149 {
150     if(ed==-1)    ed=rt[bl[x]];
151     while(x!=ed)
152     {
153         tt.set(dd[x]);
154         x=anc[x][0];
155     }
156     tt.set(dd[x]);
157 }
158 void jump2(int &x,int ed)
159 {
160     int x1=x;
161     while(x1!=1&&dep[rt[bl[x1]]]>=dep[ed])    x1=rt[bl[x1]];
162     tt|=vv[nn[x]][nn[x1]];
163     x=x1;
164 }
165 int main()
166 {
167 
168     init();
169     int i,a,b,a1,a2,t,lans=0,l;
170     scanf("%d%d%d",&n,&m,&F);
171     for(i=1;i<=n;i++)    scanf("%d",&dd[i]);
172     for(i=1;i<n;i++)
173     {
174         scanf("%d%d",&a,&b);
175         e[a].pb(b);e[b].pb(a);
176     }
177     GBLOCK::work();LCA::dfs(1,0);PRE::work();
178     while(m--)
179     {
180         scanf("%d",&t);tt.reset();
181         for(i=1;i<=t;i++)
182         {
183             scanf("%d%d",&a,&b);
184             if(F)    a^=lans,b^=lans;
185             l=lca(a,b);
186             if(a!=1&&dep[rt[bl[a]]]>=dep[l])    jump1(a,-1);
187             if(b!=1&&dep[rt[bl[b]]]>=dep[l])    jump1(b,-1);
188             jump2(a,l);
189             jump2(b,l);
190             jump1(a,l);jump1(b,l);
191         }
192         a1=tt.count();
193         a2=tt._Find_first_zero();
194         printf("%d %d\n",a1,a2);
195         lans=a1+a2;
196     }
197     return 0;
198 }
View Code

 


此方法相比直接分块然后处理边角,常数还是算小的,能够比bzoj2589https://www.cnblogs.com/hehe54321/p/9463519.html里面的做法快,但是还是过不去...

失败代码:

  1 #pragma GCC optimize(3)
  2 //#pragma GCC target("sse3","sse2","sse")
  3 #pragma GCC optimize("inline","fast-math","unroll-loops","no-stack-protector")
  4 #pragma GCC diagnostic error "-fwhole-program"
  5 #pragma GCC diagnostic error "-fcse-skip-blocks"
  6 #pragma GCC diagnostic error "-funsafe-loop-optimizations"
  7 #include<cstdio>
  8 #include<algorithm>
  9 #include<cstring>
 10 #include<vector>
 11 #include<map>
 12 using namespace std;
 13 #define fi first
 14 #define se second
 15 #define mp make_pair
 16 #define pb push_back
 17 typedef long long ll;
 18 typedef unsigned long long ull;
 19 typedef unsigned ul;
 20 typedef pair<int,int> pii;
 21 char B[1<<23],*SS=B;
 22 #define getchar() (*SS++)
 23 template<typename T>
 24 inline void read(T &x)
 25 {
 26     x=0;int f=1;char ch=getchar();
 27     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 28     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 29     x*=f;
 30 }
 31 int n,m;
 32 struct E
 33 {
 34     int to,nxt;
 35 }e[80100];
 36 int f1[40100],ne;
 37 int dd[40100];
 38 int r[40100];
 39 const int bsz=1250;
 40 ul lft[32];
 41 void init()
 42 {
 43     lft[0]=1;
 44     for(int i=1;i<32;i++)    lft[i]=lft[i-1]<<1;
 45 }
 46 struct bs
 47 {
 48 ul d[bsz];
 49 void reset(){memset(d,0,sizeof(d));}
 50 void set(int p,bool q=1)
 51 {
 52     if(q)    d[p>>5]|=lft[p&31];
 53     else    d[p>>5]&=~lft[p&31];
 54 }
 55 int count()
 56 {
 57     int ans=0;
 58     for(int i=0;i<bsz;i++)    ans+=__builtin_popcount(d[i]);
 59     return ans;
 60 }
 61 bs &operator|=(const bs &b)
 62 {
 63     for(int i=0;i<bsz;i++)    d[i]|=b.d[i];
 64     return *this;
 65 }
 66 };
 67 int bl[40100],rt[402],cnt;
 68 const int sz=100;
 69 namespace GBLOCK
 70 {
 71 int st[40100],tp;
 72 void dfs(int u,int fa)
 73 {
 74     int i,ltp=tp;
 75     for(i=f1[u];i;i=e[i].nxt)
 76         if(e[i].to!=fa)
 77         {
 78             dfs(e[i].to,u);
 79             if(tp-ltp>=sz)
 80             {
 81                 rt[++cnt]=u;
 82                 while(tp!=ltp)    bl[st[tp--]]=cnt;
 83             }
 84         }
 85     st[++tp]=u;
 86 }
 87 void work()
 88 {
 89     dfs(1,0);
 90     ++cnt;rt[cnt]=1;
 91     while(tp)    bl[st[tp--]]=cnt;
 92 }
 93 }
 94 namespace LCA
 95 {
 96 int anc[40100][17],dep[40100],l2n=16;
 97 void dfs(int u,int fa)
 98 {
 99     int i;
100     anc[u][0]=fa;
101     dep[u]=dep[fa]+1;
102     for(i=1;i<=l2n;i++)
103         anc[u][i]=anc[anc[u][i-1]][i-1];
104     for(i=f1[u];i;i=e[i].nxt)
105         if(e[i].to!=fa)
106             dfs(e[i].to,u);
107 }
108 int lca(int x,int y)
109 {
110     int t,i;
111     if(dep[x]<dep[y]){t=x;x=y;y=t;}
112     for(t=dep[x]-dep[y],i=0;t>0;t>>=1,i++)
113         if(t&1)    x=anc[x][i];
114     if(x==y)    return x;
115     for(i=l2n;i>=0;i--)
116         if(anc[x][i]!=anc[y][i])
117         {
118             x=anc[x][i];
119             y=anc[y][i];
120         }
121     return anc[x][0];
122 }
123 }
124 using LCA::lca;
125 using LCA::dep;
126 using LCA::anc;
127 int nn[40100],nnn,nn1[402];
128 bs vvv[80002];int mem;
129 int vv[402][402];//vv[i][j]:rt[i],rt[j]间答案
130 bs vis;
131 namespace TTT
132 {
133 int anr[402][10],l2n=9;
134 int dnn1[402];
135 void work()
136 {
137     int i,j;
138     for(i=1;i<=nnn;i++)    anr[i][0]=nn[r[nn1[i]]];
139     //puts("anr");
140     //for(i=1;i<=nnn;i++)    printf("%d ",anr[i][0]);
141     //puts("");
142     //return;
143     for(j=1;j<=l2n;j++)
144         for(i=1;i<=nnn;i++)
145             anr[i][j]=anr[anr[i][j-1]][j-1];
146     for(i=1;i<=nnn;i++)    dnn1[i]=dep[nn1[i]];
147 }
148 }
149 using TTT::anr;
150 using TTT::dnn1;
151 namespace PRE
152 {
153 void work()
154 {
155     int i,j;
156     for(i=1;i<=cnt;i++)
157         if(!nn[rt[i]])
158             nn[rt[i]]=++nnn,nn1[nnn]=rt[i];
159     for(i=1;i<=n;i++)
160         if(nn[i])
161         {
162             vis.reset();
163             j=i;
164             vis.set(dd[j]);
165             while(j!=1)
166             {
167                 j=anc[j][0];
168                 vis.set(dd[j]);
169                 if(nn[j])    vvv[vv[nn[i]][nn[j]]=++mem]=vis;
170             }
171         }
172 }
173 }
174 bs tt;
175 void jump1(int &x,int ed)
176 {
177     if(ed==-1)    ed=r[x];
178     while(x!=ed)
179     {
180         tt.set(dd[x]);
181         x=anc[x][0];
182     }
183     tt.set(dd[x]);
184 }
185 void jump2(int &x,int ed)
186 {
187     int i,x1=nn[x];
188     if(!x1)    return;
189     //while(x1!=1&&dep[r[x1]]>=dep[ed])    x1=r[x1];
190     for(i=TTT::l2n;i>=0;i--)
191         if(dnn1[anr[x1][i]]>=dep[ed])
192             x1=anr[x1][i];
193     x1=nn1[x1];
194     tt|=vvv[vv[nn[x]][nn[x1]]];
195     x=x1;
196 }
197 int t1[40100];
198 map<int,int> ma;
199 int main()
200 {
201     //freopen("/tmp/2589/3.in","r",stdin);
202     //freopen("/tmp/2589/3.ans","w",stdout);
203     fread(B,1,1<<23,stdin);
204     init();
205     int i,a,b,lans=0,l;
206     read(n);read(m);
207     for(i=1;i<=n;i++)    read(dd[i]),t1[++t1[0]]=dd[i];
208     sort(t1+1,t1+t1[0]+1);t1[0]=unique(t1+1,t1+t1[0]+1)-t1-1;
209     for(i=1;i<=t1[0];i++)    ma[t1[i]]=i;
210     for(i=1;i<=n;i++)    dd[i]=ma[dd[i]];
211     for(i=1;i<n;i++)
212     {
213         read(a);read(b);
214         e[++ne].to=b;e[ne].nxt=f1[a];f1[a]=ne;
215         e[++ne].to=a;e[ne].nxt=f1[b];f1[b]=ne;
216     }
217     GBLOCK::work();LCA::dfs(1,0);PRE::work();
218     for(i=1;i<=n;i++)    r[i]=rt[bl[i]];
219     TTT::work();
220     while(m--)
221     {
222         tt.reset();
223         read(a);read(b);
224         a^=lans;
225         l=lca(a,b);
226         if(dep[r[a]]>=dep[l])    jump1(a,-1);
227         if(dep[r[b]]>=dep[l])    jump1(b,-1);
228         jump2(a,l);
229         jump2(b,l);
230         jump1(a,l);jump1(b,l);
231         lans=tt.count();
232         printf("%d\n",lans);
233     }
234     return 0;
235 }
View Code

https://www.lydsy.com/JudgeOnline/problem.php?id=4812

此题也是一样的做法,得到一个bitset,之后统计答案

统计答案的话,对于bitset内每一个数字,拆成一些0~0xffff之间的数处理(因为这样就可以预处理了)

统计答案具体方法不写了。。。

注意:如果直接上面那个改改,是过不去的...常数太大

有效卡常:

1.把预处理任意两个关键点之间信息改为只预处理每个关键点到它祖先中所有关键点的信息

2.vector改邻接表

  1 #pragma GCC optimize(3)
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<vector>
  6 #include<bitset>
  7 using namespace std;
  8 #define fi first
  9 #define se second
 10 #define mp make_pair
 11 #define pb push_back
 12 typedef long long ll;
 13 typedef unsigned long long ull;
 14 typedef unsigned ul;
 15 typedef pair<int,int> pii;
 16 char B[1<<26],*SSS=B;
 17 #define getchar() (*SSS++)
 18 int n,m;
 19 struct E
 20 {
 21     int to,nxt;
 22 }e[200100];
 23 int f1[100100],ne;
 24 int dd[100100];
 25 const int bsz=938;
 26 ul lft[32];
 27 ul pw[30100][31];
 28 int low[70000],high[70000];ul an[70000][31];
 29 template<typename T>
 30 inline void read(T &x)
 31 {
 32     x=0;int f=1;char ch=getchar();
 33     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 34     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 35     x*=f;
 36 }
 37 void init()
 38 {
 39     int j,nt,k;
 40     lft[0]=1;
 41     for(int i=1;i<32;i++)    lft[i]=lft[i-1]<<1;
 42     for(ul i=1;i<=30010;i++)
 43     {
 44         pw[i][0]=1;
 45         for(j=1;j<=30;j++)   pw[i][j]=pw[i][j-1]*i;
 46     }
 47     for(ul i=1,t;i<65536;i++)
 48     {
 49         nt=0;
 50         t=i;
 51         for(j=0;j<16;j++)
 52         {
 53             if(i&lft[j])    low[i]++,t^=lft[j];
 54             else    break;
 55         }
 56         for(j=15;j>=0;j--)
 57         {
 58             if(i&lft[j])    high[i]++,t^=lft[j];
 59             else    break;
 60         }
 61         if(i!=65535)
 62         {
 63             for(j=0;j<16;j++)
 64             {
 65                 if(t&lft[j])    nt++;
 66                 else
 67                 {
 68                     for(k=0;k<=30;k++)
 69                     {
 70                         an[i][k]+=pw[nt][k];
 71                     }
 72                     nt=0;
 73                 }
 74             }
 75             for(k=0;k<=30;k++)
 76             {
 77                 an[i][k]+=pw[nt][k];
 78             }
 79             nt=0;
 80         }
 81     }
 82 }
 83 struct bs
 84 {
 85 ul d[bsz];
 86 void reset()
 87 {
 88     memset(d,0,sizeof(d));
 89 }
 90 void set(int p,bool q=1)
 91 {
 92     if(q)    d[p>>5]|=lft[p&31];
 93     else    d[p>>5]&=~lft[p&31];
 94 }
 95 bs &operator|=(const bs &b)
 96 {
 97     for(int i=0;i<bsz;i++)    d[i]|=b.d[i];
 98     return *this;
 99 }
100 ul calc(int k)
101 {
102     ul ans=0,l=0;ul t;
103     #define CAL(t) \
104     {\
105         if(t==0xffff)   l+=16;\
106         else\
107         {\
108             l+=low[t];ans+=pw[l][k];\
109             ans+=an[t][k];\
110             l=high[t];\
111         }\
112     }
113     for(int i=0;i<bsz;i++)
114     {
115         t=d[i]&0xffff;CAL(t);
116         t=(d[i]>>16);CAL(t);
117     }
118     return ans+=pw[l][k];
119 }
120 };
121 int bl[100100],rt[202],cnt;
122 const int sz=500;
123 namespace GBLOCK
124 {
125 int st[100100],tp;
126 void dfs(int u,int fa)
127 {
128     int k,ltp=tp;
129     for(k=f1[u];k;k=e[k].nxt)
130         if(e[k].to!=fa)
131         {
132             dfs(e[k].to,u);
133             if(tp-ltp>=sz)
134             {
135                 rt[++cnt]=u;
136                 while(tp!=ltp)    bl[st[tp--]]=cnt;
137             }
138         }
139     st[++tp]=u;
140 }
141 void work()
142 {
143     dfs(1,0);
144     ++cnt;rt[cnt]=1;
145     while(tp)    bl[st[tp--]]=cnt;
146 }
147 }
148 namespace LCA
149 {
150 int anc[100100][18],dep[100100],l2n=17;
151 void dfs(int u,int fa)
152 {
153     int k;
154     anc[u][0]=fa;
155     dep[u]=dep[fa]+1;
156     for(k=1;k<=l2n;k++)
157         anc[u][k]=anc[anc[u][k-1]][k-1];
158     for(k=f1[u];k;k=e[k].nxt)
159         if(e[k].to!=fa)
160             dfs(e[k].to,u);
161 }
162 int lca(int x,int y)
163 {
164     int t,i;
165     if(dep[x]<dep[y]){t=x;x=y;y=t;}
166     for(t=dep[x]-dep[y],i=0;t>0;t>>=1,i++)
167         if(t&1)    x=anc[x][i];
168     if(x==y)    return x;
169     for(i=l2n;i>=0;i--)
170         if(anc[x][i]!=anc[y][i])
171         {
172             x=anc[x][i];
173             y=anc[y][i];
174         }
175     return anc[x][0];
176 }
177 }
178 using LCA::lca;
179 using LCA::dep;
180 using LCA::anc;
181 int nn[100100],nnn;
182 bs vv[202][202];//vv[i][j]:rt[i],rt[j]间答案
183 int num[30100];bs vis;
184 namespace PRE
185 {
186 void work()
187 {
188     int i,j;
189     for(i=1;i<=cnt;i++)
190         if(!nn[rt[i]])
191             nn[rt[i]]=++nnn;
192     for(i=1;i<=n;i++)
193         if(nn[i])
194         {
195             vis.reset();
196             j=i;vis.set(dd[j]);
197             vv[nn[i]][nn[i]]=vis;
198             while(j!=1)
199             {
200                 j=anc[j][0];
201                 vis.set(dd[j]);
202                 if(nn[j])    vv[nn[i]][nn[j]]=vis;
203             }
204         }
205 }
206 }
207 bs tt;
208 void jump1(int &x,int ed)
209 {
210     if(ed==-1)    ed=rt[bl[x]];
211     while(x!=ed)
212     {
213         tt.set(dd[x]);
214         x=anc[x][0];
215     }
216     tt.set(dd[x]);
217 }
218 void jump2(int &x,int ed)
219 {
220     int x1=x;
221     while(x1!=1&&dep[rt[bl[x1]]]>=dep[ed])    x1=rt[bl[x1]];
222     tt|=vv[nn[x]][nn[x1]];
223     x=x1;
224 }
225 int main()
226 {
227     //freopen("/tmp/4812/1.in","r",stdin);
228     //freopen("/tmp/4812/1.ans","w",stdout);
229     fread(B,1,1<<26,stdin);
230     init();
231     int i,a,b,t,l;ul a1,b1;ul lans=0;
232     read(n);read(m);
233     for(i=1;i<=n;i++)    read(dd[i]);
234     for(i=1;i<n;i++)
235     {
236         read(a);read(b);
237         e[++ne].to=b;e[ne].nxt=f1[a];f1[a]=ne;
238         e[++ne].to=a;e[ne].nxt=f1[b];f1[b]=ne;
239     }
240     GBLOCK::work();LCA::dfs(1,0);PRE::work();
241     while(m--)
242     {
243         read(t);tt.reset();
244         for(i=1;i<=t;i++)
245         {
246             read(a1);read(b1);
247             a=a1^lans;b=b1^lans;
248             l=lca(a,b);
249             if(a!=1&&dep[rt[bl[a]]]>=dep[l])    jump1(a,-1);
250             if(b!=1&&dep[rt[bl[b]]]>=dep[l])    jump1(b,-1);
251             jump2(a,l);
252             jump2(b,l);
253             jump1(a,l);jump1(b,l);
254         }
255         read(t);
256         lans=tt.calc(t);
257         printf("%u\n",lans);
258     }
259     return 0;
260 }
View Code

 

posted @ 2018-08-16 21:02  hehe_54321  阅读(533)  评论(0编辑  收藏  举报
AmazingCounters.com