Bzoj4763 雪辉

 

Time Limit: 39 Sec  Memory Limit: 666 MB
Submit: 151  Solved: 80

Description

上次立下的NOIP退役Flag没有成功
 
这次就立一个WC狗牌的Flag
 
三周目的由乃被钦定成为了卡密,她立刻赶去二周目的世界寻找雪辉
 
但是按照设定,两个平行世界是没法互相影响的,也就是原则上由乃是没法去二周目世界的
 
这时候Deus又跳出来说,其实设定是作者骗你的,只要爱的力量足够强大什么都可以做到(好狗血)
 
Deus:由乃你为了雪辉是不是什么都可以做呀
 
yuno:当然啦这还用想
 
Deus:那你帮我做个题吧
 
yuno:只要不是数据结构,什么题我都做
 
Deus:出题人是那个nzhtl1477呀,他出(抄)的题除了傻逼数据结构还有啥。。。
 
yuno:你说的很有道理。。。
 
Deus:上次那个题你不是两分钟就秒了吗,这个题比那个还简单
 
yuno:(小声)其实那个是bzoj上面的大佬帮我做的
 
Deus:好吧就这么愉快的钦定了
 
给一个n个点的树,点有点权,有m次询问,每次询问多条链的并有多少种不同的点权以及它的mex
 
mex就是一个集合中最小的没有出现的非负整数,注意0要算
 
比如说集合是1,9,2,6,0,8,1,7,则出现了0,1,2,6,7,8,9这7种不同的点权,因为没有3所以mex是3

 

Input

第一行三个数n,m,意义如题所述,和一个数f
 
如果f是0,代表Deus没有使用膜法,如果f是1,代表Deus使用了膜法
 
之后一行n个数,表示点权
 
之后n-1行,每行两个数x,y,表示x和y节点之间有一条边,保证是一个树
 
之后m行,每行先是一个数a,表示这次输入a条链,紧接着2a个数(x1,y1)(x2,y2)...表示每条树链
 
如果数据被Deus施了膜法,这2a个数都要异或上上一个询问的答案lastans,如果是第一次询问则这个lastans = 0,因为每次询问有两个答案,lastans为这两个答案的和
 
如果没有膜法,则-1s并且不异或
 
数据范围:
 
设a的和为q
 
对于20%的数据,n,q<=1000,f=0
 
对于另外30%的数据,n,q<=100000,树是一条链,f=0
 
对于所有数据n,q<=100000,且点权<=30000

 

Output

m行,每行两个数表示点权种类数以及mex

 

Sample Input

10 1 1
0 0 1 0 0 2 2 0 0 0
2 3
1 2
4 5
3 4
7 8
6 7
5 6
9 10
8 9
4
1 7
3 3
1 1
9 3

Sample Output

3 3

HINT

 

可爱(口径)即正义~

 

 

Source

 

树 树分块 bitset

 

询问区间mex,理论上桶是必须要开的。这题强制在线不能树上莫队,那就只能用bitset即时维护了。

直接爬树链显然不可取,我们可以考虑树分块。

统计一条链(x,y)的答案时,拆成(x,LCA)和(y,LCA)分别处理,先向上跳到当前点所在块的中心,然后整块往上跳,再跳完零碎的部分。

因为我们要查询的是链的信息,和区域无关,所以分块应该按照深度分而不是子树大小。

stl的bitset不支持询问mex,所以要手写bitset

 

博主码代码的时候出现了很多细节上的问题,导致复杂度不稳定,无情被卡。

这是一个悲伤的故事,这个故事告诉我们永远不要迷之自信地认为自己的诡异写法能艹过正解。

 

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<cstdio>
  5 #include<cmath>
  6 #define UL long long
  7 using namespace std;
  8 const int mxn=110010;
  9 const UL ful=0xFFFFFFFFFFFFFFFF;
 10 int read(){
 11     int x=0,f=1;char ch=getchar();
 12     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 13     while(ch>='0' && ch<='9'){x=x*10-'0'+ch;ch=getchar();}
 14     return x*f;
 15 }
 16 void write(int x){
 17     if(x>9)write(x/10);
 18     putchar('0'+x%10);
 19     return;
 20 }
 21 struct edge{
 22     int v,nxt;
 23 }e[mxn<<1];
 24 int hd[mxn],mct=0;
 25 void add_edge(int u,int v){
 26     e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;return;
 27 }
 28 //
 29 int num[65537];
 30 struct BIT{
 31     UL x[471];
 32     inline void clear(){memset(x,0,sizeof x);return;}
 33     void insert(int a){
 34         int pos=a/64+1;
 35         x[pos]|=1LL<<(a%64);
 36         return;
 37     }
 38     void operator |= (const BIT &b){
 39         for(register int i=1;i<470;i++)x[i]|=b.x[i];
 40         return;
 41     }
 42     int mex(){
 43         for(int i=1;i<470;i++){
 44             if(x[i]!=ful){
 45                 int res=0;
 46                 UL tmp=x[i];
 47                 while(tmp&1){
 48                     res++;
 49                     tmp>>=1;
 50                 }
 51                 return res+(i-1)*64;
 52             }
 53         }
 54         return 469*64-1;
 55     }
 56     int calc(){
 57         int cnt=0;
 58         for(int i=1;i<470;i++){
 59             if(!x[i])continue;
 60             if(x[i]==ful)cnt+=64;
 61             else{
 62                 UL tmp=x[i];
 63                 cnt+=num[(tmp&65535)]+num[(tmp>>16)&65535];
 64                 tmp>>=32;
 65                 cnt+=num[(tmp&65535)]+num[(tmp>>16)&65535];
 66             }
 67         }
 68         return cnt;
 69     }
 70 }bt[320][320],res;
 71 int block=0;
 72 int dep[mxn],mx[mxn],bct=0;
 73 int Cid[mxn],C[mxn],Cfa[mxn];
 74 int fa[mxn][19];
 75 void DFS(int u,int ff){
 76     mx[u]=0;dep[u]=dep[ff]+1;
 77     for(int i=1;i<=17;i++)fa[u][i]=fa[fa[u][i-1]][i-1];
 78     for(int i=hd[u];i;i=e[i].nxt){
 79         int v=e[i].v;if(v==ff)continue;
 80         fa[v][0]=u;
 81         DFS(v,u);
 82         mx[u]=max(mx[u],mx[v]+1);
 83     }
 84     if(mx[u]>=block || u==1){
 85         mx[u]=0;
 86         bct++; Cid[u]=bct; C[bct]=u; Cfa[bct]=0;
 87     }
 88     return;
 89 }
 90 int LCA(int x,int y){
 91     if(dep[x]<dep[y])swap(x,y);
 92     for(int i=17;i>=0;i--)if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
 93     if(x==y)return x;
 94     for(int i=17;i>=0;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
 95     return fa[x][0];
 96 }
 97 int n,Q,F;
 98 int lastans=0;
 99 int w[mxn];
100 void Build(){
101     block=sqrt(n+0.5);
102     DFS(1,0);
103     for(int i=1;i<=bct;i++){
104         int u=C[i];
105         res.clear();
106         res.insert(w[u]);u=fa[u][0];
107         while(u){
108             res.insert(w[u]);
109             //
110             if(Cid[u]){
111                 bt[i][Cid[u]]=res;
112                 if(!Cfa[i])Cfa[i]=u;
113             }
114             //
115             u=fa[u][0];
116         }
117     }
118     return;
119 }
120 void query(int x,int y){
121     if(dep[x]<dep[y])swap(x,y);
122     if(dep[x]-dep[y]<=block){
123         while(dep[x]>=dep[y]){
124             res.insert(w[x]);
125             x=fa[x][0];
126         }
127         return;
128     }
129     while(dep[x]>=dep[y] && !Cid[x]){
130         res.insert(w[x]);
131         x=fa[x][0];
132     }
133     int tmp=x;
134     while(dep[Cfa[Cid[tmp]]]>=dep[y]){
135         tmp=Cfa[Cid[tmp]];
136     }
137     if(tmp^x)res|=bt[Cid[x]][Cid[tmp]];
138     x=tmp;
139     while(dep[x]>=dep[y]){
140         res.insert(w[x]);
141         x=fa[x][0];
142     }
143     return;
144 }
145 void solve(){
146     int a=read(),x,y;
147     res.clear();
148     while(a--){
149         x=read();y=read();
150         if(F){x^=lastans;y^=lastans;}
151         //
152         int tmp=LCA(x,y);
153         query(x,tmp);query(y,tmp);
154         //
155     }
156     int ans1=res.mex();
157     int ans2=res.calc();
158 //    printf("%d %d\n",ans2,ans1);
159     write(ans2);putchar(' ');write(ans1);puts("");
160     lastans=ans1+ans2;//
161     return;
162 }
163 int main(){
164 //    freopen("in.txt","r",stdin);
165 //    freopen("out2.txt","w",stdout);
166     int i,j,u,v;
167     n=read();Q=read();F=read();
168     for(i=1;i<=n;i++)w[i]=read();
169     for(i=1;i<n;i++){
170         u=read();v=read();
171         add_edge(u,v);
172         add_edge(v,u);
173     }
174     for(i=1;i<=65535;i++){
175         int tmp=i;
176         while(tmp){
177             num[i]++;
178             tmp-=tmp&-tmp;
179         }
180     }
181     Build();
182     while(Q--)solve();
183     return 0;
184 }

 

posted @ 2017-07-05 18:42  SilverNebula  阅读(348)  评论(0编辑  收藏  举报
AmazingCounters.com