记一次改题

最近考试题一直改不完,不过还是想写一篇博客

[NOIP模拟测试26(A)T2]

下午2:00 下定决心改过T2(跟他们说复习一下树剖板子)

下午3:00终于看懂原理,开始码

下午3:01突然发现考试代码改一改可以成标准的暴力

下午3:30发现暴力可以得到87分,于是动了邪念。。。。(决定用分块艹过)

期间请教死缠了skyh和remarkable 大佬,几次产生放弃念头(唉,我还是打正解吧)

8:30尝试更改块的大小,终于AC。

学到的东西:

1.分块万能。

自己YY的树上分块:

 1 //预处理
 2 void dfs(const int x,const int kp){
 3     dfn[x]=++tot;
 4     if(t&&d[x]%t==0)ed[x]=1;
 5     tp[x]=kp;
 6     for(int i=head[x],y;i;i=nxt[i])
 7     {
 8         y=to[i];
 9         d[y]=d[x]+1;
10         if(ed[x])tp[y]=y,er[y].set(a[y]),dfs(y,y);
11         else tp[y]=tp[x],er[y]=er[x],er[y].set(a[y]),dfs(y,kp);
12     }
13 }
14 //询问
15 for(register int i=1;i<=c;++i)
16 {
17     register int now=p[i];
18     while(fa[tp[now]]&&d[fa[tp[now]]]>=d[lc])
19     {
20         s[i]|=er[now];
21         now=fa[tp[now]];
22     }
23     while(1)
24     {
25         s[i].set(a[now]);
26         if(now==lc)break;
27         now=fa[now];
28     }
29 }
View Code

2.手打bitset

 

 1 struct bitset{
 2     unsigned long long bit[16];
 3     inline void reset(){
 4         for(register int i=0;i^16;i+=4) bit[i]=bit[i|1]=bit[i|2]=bit[i|3]=0;
 5     }
 6     inline friend void operator |=(bitset &a,const bitset &b){
 7         for(register int i=0;i^16;i+=4) a.bit[i]|=b.bit[i],a.bit[i|1]|=b.bit[i|1],a.bit[i|2]|=b.bit[i|2],a.bit[i|3]|=b.bit[i|3];
 8     }
 9     inline friend bitset operator |(const bitset &a,const bitset &b){
10         bitset ans;
11         for(register int i=0;i^16;i+=4)            ans.bit[i]=a.bit[i]|b.bit[i],ans.bit[i|1]=a.bit[i|1]|b.bit[i|1],ans.bit[i|2]=a.bit[i|2]|b.bit[i|2],ans.bit[i|3]=a.bit[i|3]|b.bit[i|3];
12         return ans;
13     }
14     inline void set(const int x){
15         bit[x/64]|=(unsigned long long)1<<(x&63);
16     }
17     inline int count(){
18         register int cnt=0;
19         for(int i=0;i<16;++i)
20             cnt+=ct[bit[i]&65535]+ct[(bit[i]>>16)&65535]+ct[(bit[i]>>32)&65535]+ct[(bit[i]>>48)&65535];
21         return cnt;
22     }
23 }; 
View Code

 

 

 

3.适时调整块的大小

4.多想一些东西。

AC代码:

  1 #include<cstring>
  2 #include<iostream>
  3 #include<cstdio>
  4 #include<cmath>
  5 using namespace std;
  6 const int L=1<<20|1;
  7 char buf[L],*S,*T;
  8 #define getchar() ((S==T&&(T=(S=buf)+fread(buf,1,L,stdin),S==T))?EOF:*S++)
  9 int dfn[300005],f[300005][20];
 10 int t;
 11 int head[300005],to[300005],nxt[300005],cnt,p[6],a[300005],nk[6],c,ans,n,m,q,tot,d[300005],tcnt[105],yk[105],maxd,tp[300005],ct[65600],fa[300005];
 12 char ed[300005];
 13 struct bitset{
 14     #define lowbit(x) (x&-x)
 15     unsigned long long bit[16];
 16     inline void reset(){
 17         for(register int i=0;i^16;i+=4) bit[i]=bit[i|1]=bit[i|2]=bit[i|3]=0;
 18     }
 19     inline friend void operator |=(bitset &a,const bitset &b){
 20         for(register int i=0;i^16;i+=4) a.bit[i]|=b.bit[i],a.bit[i|1]|=b.bit[i|1],a.bit[i|2]|=b.bit[i|2],a.bit[i|3]|=b.bit[i|3];
 21     }
 22     inline friend bitset operator |(const bitset &a,const bitset &b){
 23         bitset ans;
 24         for(register int i=0;i^16;i+=4) 
 25             ans.bit[i]=a.bit[i]|b.bit[i],ans.bit[i|1]=a.bit[i|1]|b.bit[i|1],ans.bit[i|2]=a.bit[i|2]|b.bit[i|2],ans.bit[i|3]=a.bit[i|3]|b.bit[i|3];
 26         return ans;
 27     }
 28     inline void set(const int x){
 29         bit[x/64]|=(unsigned long long)1<<(x&63);
 30     }
 31     inline int count(){
 32         register int cnt=0;
 33         for(int i=0;i<16;++i)
 34             cnt+=ct[bit[i]&65535]+ct[(bit[i]>>16)&65535]+ct[(bit[i]>>32)&65535]+ct[(bit[i]>>48)&65535];
 35         return cnt;
 36     }
 37 }s[6],ak[32],er[300005];
 38 inline void Add(const int u,const int v)
 39 {
 40     to[++cnt]=v;
 41     nxt[cnt]=head[u];
 42     head[u]=cnt;
 43     return ;
 44 }
 45 void dfs(const int x,const int kp){
 46     dfn[x]=++tot;
 47     if(t&&d[x]%t==0)ed[x]=1;
 48     tp[x]=kp;
 49     for(int i=head[x],y;i;i=nxt[i])
 50     {
 51         y=to[i];
 52         d[y]=d[x]+1;
 53         if(ed[x])tp[y]=y,er[y].set(a[y]),dfs(y,y);
 54         else tp[y]=tp[x],er[y]=er[x],er[y].set(a[y]),dfs(y,kp);
 55     }
 56 }
 57 int Q[300005],l,r;
 58 inline int lca(int a,int b)
 59 {
 60     if(d[a]>d[b])a^=b^=a^=b;
 61     for(int t=18;t>=0;t--)
 62         if(f[b][t]&&d[a]<=d[f[b][t]])b=f[b][t];
 63     if(a==b)return a;
 64     for(int t=18;t>=0;t--)
 65         if(f[a][t]&&f[a][t]!=f[b][t])a=f[a][t],b=f[b][t];
 66     return f[a][0];
 67 }
 68 inline int read(register int x=0,register char ch=getchar()){
 69     while(ch<48||ch>57) ch=getchar();
 70     while(ch>=48&&ch<=57) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
 71     return x;
 72 }
 73 char cp[10],top;
 74 inline void write(int x){
 75     do{
 76         cp[top++]=x%10,x/=10;
 77     }while(x);
 78     do{
 79         putchar(cp[--top]+48);
 80     }while(top);
 81     putchar(10);
 82 }
 83 int main()
 84 {
 85     n=read(); m=read(); q=read();
 86     for(int i=1;i<=65535;++i) ct[i]=ct[(i&-i)^i]+1;
 87     yk[1]=1,yk[2]=2,yk[4]=3,yk[8]=4,yk[16]=5;
 88     for(int i=1;i<=31;++i)
 89         for(int j=1;j<=5;++j)
 90             if(i&(1<<(j-1)))tcnt[i]++;
 91     for(int i=2;i<=n;Add(fa[i],i),++i) fa[i]=read();
 92     for(int i=1;i<=n;++i) a[i]=read();
 93     t=pow(n,0.555);
 94     dfs(1,1);
 95     for(int j=1;j<=n;++j){
 96         f[j][0]=fa[j];
 97         for(int i=0;i<18;++i)
 98             f[j][i+1]=f[f[j][i]][i];
 99     }
100     while(q--)
101     {
102         c=read(); ans=0x7f7f7f7f;
103         for(register int i=1;i<=c;++i) p[i]=read();
104         register int now=-1,pa,pb;
105         for(register int i=1;i<=c;++i)
106             for(register int j=i+1;j<=c;++j)
107                 if(abs(dfn[p[i]]-dfn[p[j]])>now)pa=p[i],pb=p[j],now=abs(dfn[p[i]]-dfn[p[j]]);
108         register int lc=lca(pa,pb);
109         for(register int i=1;i<=c;++i)
110         {
111             register int now=p[i];
112             while(fa[tp[now]]&&d[fa[tp[now]]]>=d[lc])
113             {
114                 s[i]|=er[now];
115                 now=fa[tp[now]];
116             }
117             while(1)
118             {
119                 s[i].set(a[now]);
120                 if(now==lc)break;
121                 now=fa[now];
122             }
123         }
124         for(register int i=1;i<1<<c;++i)
125         {
126             ak[i]=ak[i^(i&-i)]|s[yk[i&-i]];
127             ans=min(ans,(int)ak[i].count()/tcnt[i]);
128         }
129         for(register int i=1;i<=c;++i)s[i].reset();
130         write(ans*c);
131     }
132     return 0;
133 }
View Code
posted on 2019-08-19 21:37  _kx  阅读(181)  评论(3)    收藏  举报