BZOJ 2589 Spoj 10707 Count on a tree II 强制在线莫队算法(TLE)

来源:互联网 发布:php模拟登录get 编辑:程序博客网 时间:2024/06/06 09:52

题目大意:给定一棵树,每个节点有一个颜色,多次询问某条路径上颜色数量,强制在线

正解是块状数组,强制在线莫队会TLE到死,想AC这道题的不用看了

如果朴素的跑树上莫队其实并不难- - 但是强制在线

因此我们可以考虑强制在线莫队算法

将树分成O(n^1/3)块,每块大小O(n^2/3)

记录每两块之间的答案、每种颜色的出现次数和哪些点被记录到了答案中

每次查询先找到两端点所在块的端点的答案,然后暴力用莫队转移即可

空间复杂度O(n^1/3)*O(n^1/3)*O(n)=O(n^5/3)

预处理时间复杂度O(n^1/3)*O(n^1/3)*O(n)=O(n^5/3)

单次询问时间复杂度O(n^2/3)


然后。。。被卡常数。。。明明本机只要不到11秒就能全部出解。。。BZ渣评测机怎么这么慢。。。

读入优化。。。寻址优化。。。short压内存。。。内嵌汇编强制inline。。。函数改成宏。。。倍增LCA改成RMQLCA。。。三分法修改块的大小。。。还有啥。。。bool改成bitset。。。随机数选根防卡。。。还特意去切了王室联邦练习树分块。。。最后还在结尾附加一段注释增强一下信仰。。。

从早上卡到现在。。。 加上昨天写的版本一共挂了七篇。。。整整七篇。。。。。。。。。。。。。。。。。。。。。

发个本地评测的图吧。。。 此题精神AC了。。。


我が生涯に、一片の悔いなし。。。。。

#include <bitset>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define M 40002#define B 95#define Change(x,f,v,ans) {  \if(v[x])                  \{                          \if(!--f[a[x]])          \--ans;               \v[x]=0;                   \}                              \else                            \{                                \if(!f[a[x]]++)                \++ans;                     \v[x]=1;                         \}                                    \}#define swap(x,y) {int t=x;x=y;y=t;}using namespace std;struct abcd{int to,next;}table[M<<1];int head[M],tot;int n,m,b,cnt,last_ans;int a[M],fa[M],dpt[M],log2[M<<1],min_dpt[M<<1][20],into[M];int belong[M],root[M],stack[M],top;unsigned short f[B*(B-1)/2*M+M];bitset<M> v[B][B];int ans[B][B],pos[B][B];__inline__ __attribute__((always_inline)) void Add(int x,int y){table[++tot].to=y;table[tot].next=head[x];head[x]=tot;}void DFS(int x){static int T;int i,bottom=top;dpt[x]=dpt[fa[x]]+1;min_dpt[into[x]=++T][0]=x;for(i=head[x];i;i=table[i].next)if(table[i].to!=fa[x]){fa[table[i].to]=x;DFS(table[i].to);if(top-bottom>=b){while(top!=bottom)belong[stack[top--]]=cnt;root[cnt++]=x;}min_dpt[++T][0]=x;}stack[++top]=x;}/*__inline__ __attribute__((always_inline)) void Change(int x,unsigned short f[M],bitset<M> &v,int &ans){if(v[x]){if(!--f[a[x]])--ans;}else{if(!f[a[x]]++)++ans;}v[x]=!v[x];}*/void Pretreatment(int x,int y,unsigned short f[M],bitset<M> &v,int &ans){if(dpt[x]<dpt[y])swap(x,y);while(dpt[x]>dpt[y]){Change(x,f,v,ans);x=fa[x];}while(x!=y){Change(x,f,v,ans);Change(y,f,v,ans);x=fa[x];y=fa[y];}}__inline__ __attribute__((always_inline)) int Min(int x,int y){return dpt[x]<dpt[y]?x:y;}__inline__ __attribute__((always_inline)) int LCA(int x,int y){x=into[x];y=into[y];if(x>y) swap(x,y);int j=log2[y-x+1];return Min(min_dpt[x][j],min_dpt[y-(1<<j)+1][j]);}int Query(int x,int y){static unsigned short f[M];static bitset<M> v;static int tim1[M],tim2[M],T;++T;if(belong[x]>belong[y])swap(x,y);unsigned short *F=::f+pos[belong[x]][belong[y]];bitset<M> &V=::v[belong[x]][belong[y]];int ans=::ans[belong[x]][belong[y]];int l=root[belong[x]],r=root[belong[y]];unsigned short temp,a_t,lca=LCA(l,x);for(int temp=x;temp!=lca;temp=fa[temp]){a_t=a[temp];if(tim1[a_t]!=T)tim1[a_t]=T,f[a_t]=F[a_t];if(tim2[temp]!=T)tim2[temp]=T,v[temp]=V[temp];Change(temp,f,v,ans);}for(temp=l;temp!=lca;temp=fa[temp]){a_t=a[temp];if(tim1[a_t]!=T)tim1[a_t]=T,f[a_t]=F[a_t];if(tim2[temp]!=T)tim2[temp]=T,v[temp]=V[temp];Change(temp,f,v,ans);}lca=LCA(r,y);for(temp=y;temp!=lca;temp=fa[temp]){a_t=a[temp];if(tim1[a_t]!=T)tim1[a_t]=T,f[a_t]=F[a_t];if(tim2[temp]!=T)tim2[temp]=T,v[temp]=V[temp];Change(temp,f,v,ans);}for(temp=r;temp!=lca;temp=fa[temp]){a_t=a[temp];if(tim1[a_t]!=T)tim1[a_t]=T,f[a_t]=F[a_t];if(tim2[temp]!=T)tim2[temp]=T,v[temp]=V[temp];Change(temp,f,v,ans);}temp=LCA(x,y);a_t=a[temp];if(tim1[a_t]!=T)tim1[a_t]=T,f[a_t]=F[a_t];if(tim2[temp]!=T)tim2[temp]=T,v[temp]=V[temp];Change(temp,f,v,ans);return ans;}namespace IStream{      const int L=1<<15;      char buffer[L],*S,*T;    char Get_Char()      {          if(S==T)          {              T=(S=buffer)+fread(buffer,1,L,stdin);              if(S==T) return EOF;          }          return *S++;      }      int Get_Int()      {          char c;          int re=0;          for(c=Get_Char();c<'0'||c>'9';c=Get_Char());          while(c>='0'&&c<='9')              re=(re<<1)+(re<<3)+(c-'0'),c=Get_Char();          return re;      }  }class OStream{      private:          static const int L=1<<15;          char stack[20];int top;          char buffer[L],*S;      public:          OStream()          {              S=buffer;          }          void Put_Int(int x,bool flag)          {              if(flag) stack[++top]='\n';              if(!x) stack[++top]='0';              else while(x)                  stack[++top]=x%10+'0',x/=10;              while(top)              {                  if(S==buffer+L-1)                  {                      //fwrite(buffer,1,S-buffer,stdout);                      printf("%s",buffer);S=buffer;                  }                  *S++=stack[top--];            }          }          ~OStream()        {              //fwrite(buffer,1,S-buffer,stdout);            *S=0;printf("%s",buffer);        }  }os;int main(){#ifndef ONLINE_JUDGEfreopen("2589.in","r",stdin);freopen("2589.out","w",stdout);#endifstatic pair<int,int*> b[M];int i,j,x,y;cin>>n>>m;::b=420;for(i=1;i<=n;i++)b[i].first=IStream::Get_Int(),b[i].second=&a[i];sort(b+1,b+n+1);for(i=1;i<=n;i++){static int tot=0;if(i==1||b[i].first!=b[i-1].first)++tot;*b[i].second=tot;}for(i=1;i<n;i++){x=IStream::Get_Int();y=IStream::Get_Int();Add(x,y);Add(y,x);}int r=6854654%n+1;DFS(r);if(!cnt) root[cnt++]=r;while(top)belong[stack[top--]]=cnt-1;log2[0]=-1;for(i=1;i<=n-1<<1;i++)log2[i]=log2[i>>1]+1;for(j=1;j<=log2[n-1<<1];j++)for(i=1;i+(1<<j)-1<=n-1<<1;i++)min_dpt[i][j]=Min(min_dpt[i][j-1],min_dpt[i+(1<<j-1)][j-1]);for(i=0;i<cnt;i++)for(j=i+1;j<cnt;j++){static int T;pos[i][j]=(++T)*M;if(j==i+1)Pretreatment(root[i],root[j],f+pos[i][j],v[i][j],ans[i][j]);else{memcpy(f+pos[i][j],f+pos[i][j-1],sizeof(unsigned short)*M);v[i][j]=v[i][j-1];ans[i][j]=ans[i][j-1];Pretreatment(root[j],root[j-1],f+pos[i][j],v[i][j],ans[i][j]);}}for(i=1;i<=m;i++){x=IStream::Get_Int()^last_ans;y=IStream::Get_Int();os.Put_Int(last_ans=Query(x,y),i<m);}/*os.Put_Int(2147483647,true);sort(root,root+cnt);for(i=0;i<cnt;i++)os.Put_Int(root[i],true);*/return 0;}/*アナタガ望ムノナラバ犬ノヤウニ従顺ニ纽ニ縄ニ锁ニ缚ラレテアゲマセウ*/

卡常数狗我操你妈。

总有一天我会用莫队算法卡过这道题的。

1 0
原创粉丝点击