2021.7.21考试总结[NOIP模拟22]
终于碾压小熠了乐死了
T1 d
小贪心一波直接出正解,没啥好说的(bushi
好像可以主席树暴力找,但我怎么可能会呢?好像可以堆优化简单找,但我怎么可能想得到呢?
那怎么办?昨天两道单调指针加桶,我直接使用经典方法。
先把a该删的全删了,之后按a填一个按b删一个,O(m)枚举所有情况。
code:
1 #include<bits/stdc++.h> 2 #define debug exit(0) 3 #define LL long long 4 using namespace std; 5 const int NN=1e5+5; 6 int n,T,m,ta[NN],tb[NN],tma,tmb,tmp; 7 struct jz{ 8 int a,b,id; 9 }s[NN],sa[NN],sb[NN]; 10 LL ans; 11 bool flag=0,vis[NN]; 12 inline int Min(int a,int b){ return a<b?a:b; } 13 inline LL Max(LL a,LL b){ return a<b?b:a; } 14 inline bool cmp1(jz x,jz y){ return x.a==y.a?(x.b<y.b):(x.a<y.a); } 15 inline bool cmp2(jz x,jz y){ return x.b==y.b?(x.a<y.a):(x.b<y.b); } 16 inline int read(){ 17 int x=0,f=1; 18 char ch=getchar(); 19 while(ch<'0'||ch>'9'){ 20 if(ch=='-') f=-1; 21 ch=getchar(); 22 } 23 while(ch>='0'&&ch<='9'){ 24 x=(x<<1)+(x<<3)+(ch^48); 25 ch=getchar(); 26 } 27 return x*f; 28 } 29 void write(LL x){ 30 if(x<0) putchar('-'), x=-x; 31 if(x>9) write(x/10); 32 putchar(x%10+'0'); 33 } 34 void clear(){ 35 ans=0; tma=tmb=INT_MAX; tmp=1; 36 memset(vis,0,sizeof(vis)); 37 memset(ta,0,sizeof(ta)); 38 memset(tb,0,sizeof(tb)); 39 } 40 void solve(){ 41 while(!ta[tma]) ++tma; 42 while(!tb[tmb]) ++tmb; 43 ans=max(ans,1ll*tma*tmb); 44 } 45 int main(){ 46 freopen("d2.in","r",stdin); 47 freopen("out","w",stdout); 48 T=read(); 49 while(T--){ 50 clear(); 51 n=read(); m=read(); 52 for(int i=1;i<=n;i++) s[i].a=read(), s[i].b=read(), s[i].id=i; 53 for(int i=1;i<=n;i++){ 54 sa[i]=s[i]; sb[i]=s[i]; 55 ++ta[s[i].a]; ++tb[s[i].b]; 56 tma=Min(tma,s[i].a); tmb=Min(tmb,s[i].b); 57 } 58 sort(sa+1,sa+n+1,cmp1); sort(sb+1,sb+n+1,cmp2); 59 for(int i=1;i<=m;i++){ 60 vis[sa[i].id]=1; 61 --ta[sa[i].a]; --tb[sa[i].b]; 62 } 63 solve(); 64 for(int i=1;i<=m;i++){ 65 if(sa[m-i+1].b<=tmb) continue; 66 vis[sa[m-i+1].id]=0; ++ta[sa[m-i+1].a]; ++tb[sa[m-i+1].b]; 67 if(sa[m-i+1].a<tma) tma=sa[m-i+1].a; 68 while(vis[sb[tmp].id]) tmp++; 69 vis[sb[tmp].id]=1; --ta[sb[tmp].a]; --tb[sb[tmp].b]; 70 solve(); 71 } 72 write(ans); putchar('\n'); 73 } 74 return 0; 75 }
T2 e
没想到吧又是道主席树
首先认识到联通块由所有点的LCA与点的简单路径构成。那么我们就应该写一种数据结构,支持查找链上的前驱后继,主席树。
不会怎么办?问JYFHYX。树链剖分套线段树套平衡树加XIN_TEAM优化直接A过。
1 #include<bits/stdc++.h> 2 #define inf 2e9 3 #define lid id<<1 4 #define rid id<<1|1 5 using namespace std; 6 inline int read() 7 { 8 int x=0,f=1; 9 char ch=getchar(); 10 while(ch<'0'||ch>'9') 11 { 12 if(ch=='-') f=-1; 13 ch=getchar(); 14 } 15 while(ch>='0'&&ch<='9') 16 { 17 x=(x<<1)+(x<<3)+(ch^48); 18 ch=getchar(); 19 } 20 return x*f; 21 } 22 const int maxn=2e6+1; 23 struct treap{ 24 int l,r,size,cnt,dat,val; 25 }a[maxn]; 26 struct seg_tree{ 27 int l,r,root,lazy; 28 }tr[maxn<<2]; 29 int n,q,type,tot; 30 struct node{ 31 int to,nxt; 32 }e[maxn*2]; 33 int head[maxn]; 34 bool flag=1; 35 int val[maxn]; 36 bool vis[100001]; 37 int w[maxn],num; 38 int dfn[maxn],size[maxn],son[maxn],fa[maxn],top[maxn]; 39 int dep[maxn],cnt; 40 int cz[maxn],rr,k; 41 inline void add(int x,int y) 42 { 43 e[++num].to=y; 44 e[num].nxt=head[x]; 45 head[x]=num; 46 if(x!=y+1&&y!=x+1) flag=0; 47 swap(x,y); 48 e[++num].to=y; 49 e[num].nxt=head[x]; 50 head[x]=num; 51 } 52 inline int New(int val) 53 { 54 a[++tot].val=val; 55 a[tot].dat=rand(); 56 a[tot].cnt=a[tot].size=1; 57 return tot; 58 } 59 inline void pushup(int p) 60 { 61 a[p].size=a[a[p].l].size+a[a[p].r].size+1; 62 } 63 inline int merge(int x,int y) 64 { 65 if(!x||!y) 66 return x|y; 67 if(a[x].dat<a[y].dat) 68 { 69 a[x].r=merge(a[x].r,y); 70 pushup(x); 71 return x; 72 } 73 else 74 { 75 a[y].l=merge(x,a[y].l); 76 pushup(y); 77 return y; 78 } 79 } 80 inline void split(int now,int kk,int &x,int &y) 81 { 82 if(!now) 83 { 84 x=y=0; 85 return ; 86 } 87 if(kk>=a[now].val) 88 { 89 x=now; 90 split(a[now].r,kk,a[now].r,y); 91 } 92 else 93 { 94 y=now; 95 split(a[now].l,kk,x,a[now].l); 96 } 97 pushup(now); 98 } 99 inline void insert(int &root,int val) 100 { 101 int x,y; 102 split(root,val,x,y); 103 root=merge(merge(x,New(val)),y); 104 } 105 void build(int id,int l,int r) 106 { 107 tr[id].l=l; tr[id].r=r; 108 if(l==r) 109 { 110 tr[id].root=New(w[l]); 111 return ; 112 } 113 for(int j=l;j<=r;j++) 114 insert(tr[id].root,w[j]); 115 int mid=(l+r)>>1; 116 build(lid,l,mid); 117 build(rid,mid+1,r); 118 } 119 inline int pre(int &root,int val) 120 { 121 int x,y,ans; 122 split(root,val-1,x,y); 123 if(!x) return -inf; 124 int kk=x; 125 while(a[kk].r) 126 kk=a[kk].r; 127 ans=a[kk].val; 128 root=merge(x,y); 129 return ans; 130 } 131 inline int nxt(int &root,int val) 132 { 133 int x,y,ans; 134 split(root,val,x,y); 135 if(!y) return inf; 136 int kk=y; 137 while(a[kk].l) 138 kk=a[kk].l; 139 ans=a[kk].val; 140 root=merge(x,y); 141 return ans; 142 } 143 inline int askpre(int id,int l,int r,int d) 144 { 145 if(tr[id].l>=l&&tr[id].r<=r) 146 return pre(tr[id].root,d); 147 int mid=(tr[id].l+tr[id].r)>>1; 148 int ans=-inf; 149 if(l<=mid) 150 ans=max(ans,askpre(lid,l,r,d)); 151 if(r>mid) 152 ans=max(ans,askpre(rid,l,r,d)); 153 return ans; 154 } 155 inline int asknxt(int id,int l,int r,int d) 156 { 157 if(tr[id].l>=l&&tr[id].r<=r) 158 return nxt(tr[id].root,d); 159 int mid=(tr[id].l+tr[id].r)>>1; 160 int ans=inf; 161 if(l<=mid) 162 ans=min(ans,asknxt(lid,l,r,d)); 163 if(r>mid) 164 ans=min(ans,asknxt(rid,l,r,d)); 165 return ans; 166 } 167 void dfs1(int x,int f) 168 { 169 size[x]=1; 170 for(int i=head[x];i;i=e[i].nxt) 171 { 172 int y=e[i].to; 173 if(y==f) continue; 174 dep[y]=dep[x]+1; 175 fa[y]=x; 176 dfs1(y,x); 177 size[x]+=size[y]; 178 if(size[son[x]]<size[y]) 179 son[x]=y; 180 } 181 } 182 void dfs2(int x,int f) 183 { 184 top[x]=f; 185 dfn[x]=++cnt; 186 w[cnt]=val[x]; 187 if(!son[x]) return ; 188 dfs2(son[x],f); 189 for(int i=head[x];i;i=e[i].nxt) 190 { 191 int y=e[i].to; 192 if(y!=fa[x]&&y!=son[x]) 193 dfs2(y,y); 194 } 195 } 196 inline int treepre(int x,int y,int jb) 197 { 198 int ans=-inf; 199 while(top[x]!=top[y]) 200 { 201 if(dep[top[x]]<dep[top[y]]) 202 swap(x,y); 203 ans=max(ans,askpre(1,dfn[top[x]],dfn[x],jb)); 204 x=fa[top[x]]; 205 } 206 if(dep[x]>dep[y]) 207 swap(x,y); 208 ans=max(ans,askpre(1,dfn[x],dfn[y],jb)); 209 return ans; 210 } 211 inline int treenxt(int x,int y,int jb) 212 { 213 int ans=inf; 214 while(top[x]!=top[y]) 215 { 216 if(dep[top[x]]<dep[top[y]]) 217 swap(x,y); 218 ans=min(ans,asknxt(1,dfn[top[x]],dfn[x],jb)); 219 x=fa[top[x]]; 220 } 221 if(dep[x]>dep[y]) 222 swap(x,y); 223 ans=min(ans,asknxt(1,dfn[x],dfn[y],jb)); 224 return ans; 225 } 226 inline int LCA(int x, int y) 227 { 228 while(top[x]!=top[y]) 229 { 230 if(dep[top[x]]<dep[top[y]]) 231 swap(x,y); 232 x=fa[top[x]]; 233 } 234 return dep[x]<dep[y]?x:y; 235 } 236 inline void dfs3(int x,int goal,int &sum) 237 { 238 if(!x) return ; 239 if(vis[x]) return ; 240 vis[x]=1; 241 sum=min(sum,abs(val[x]-rr)); 242 if(x==goal) return ; 243 dfs3(fa[x],goal,sum); 244 } 245 signed main() 246 { 247 //freopen("e7.in","r",stdin); 248 //freopen("out","w",stdout); 249 srand(time(0)); 250 n=read(),q=read(),type=read(); 251 for(int i=1;i<=n;i++) val[i]=read(); 252 for(int i=1;i<n;i++) add(read(),read()); 253 dfs1(1,0); 254 dfs2(1,1); 255 if(flag==1) 256 { 257 for(int i=1;i<=q;i++) 258 { 259 memset(vis,0,sizeof(vis)); 260 rr=read(),k=read(); 261 for(int j=1;j<=k;j++) cz[j]=read(); 262 int ans=inf; 263 int lca=cz[1]; 264 for(int j=2;j<=k;j++) 265 lca=LCA(lca,cz[j]); 266 for(int j=1;j<=k;j++) 267 dfs3(cz[j],lca,ans); 268 printf("%d\n",ans); 269 } 270 return 0; 271 } 272 else 273 { 274 build(1,1,n); 275 int ans=0; 276 for(int i=1;i<=q;i++) 277 { 278 rr=read(),k=read(); 279 for(int j=1;j<=k;j++) cz[j]=((read()-1+type*ans)%n)+1; 280 ans=inf; 281 int lca=cz[1]; 282 for(int j=2;j<=k;j++) 283 lca=LCA(lca,cz[j]); 284 for(int j=1,tmp;j<=k;j++) 285 { 286 tmp=treepre(lca,cz[j],rr+1); 287 if(ans>abs(tmp-rr)) ans=abs(tmp-rr); 288 tmp=treenxt(lca,cz[j],rr-1); 289 if(ans>abs(tmp-rr)) ans=abs(tmp-rr); 290 } 291 printf("%d\n",ans); 292 } 293 } 294 }
但一般人显然没有那种毅力。学zxs吧。
从根开始DFS,途中插入每个值,继承父亲的信息,之后查找链上r的前驱和后继更新答案。
查前驱先查右儿子,如果有直接返回,不然就查左儿子,后继同理。具体看代码。
code:
1 #include<bits/stdc++.h> 2 #define debug exit(0) 3 using namespace std; 4 const int NN=1e5+5,inf=2e9; 5 int n,q,R[NN<<2],k,type,a[NN],to[NN<<1],nex[NN<<1],head[NN],num,last,has[NN<<3],ext,h; 6 int dep[NN],siz[NN],son[NN],fa[NN],top[NN],dfn[NN],id[NN],cnt; 7 vector<int>ask[NN<<2]; 8 struct zxs_tree{ 9 int sum[NN*80],root[NN*80],tot,lc[NN*80],rc[NN*80]; 10 void pushup(int rt){ 11 sum[rt]=sum[lc[rt]]+sum[rc[rt]]; 12 } 13 void insert(int x,int &rt,int fom,int l,int r){ 14 rt=++tot; 15 sum[rt]=sum[fom]+1; lc[rt]=lc[fom]; rc[rt]=rc[fom]; 16 if(l==r) return; 17 int mid=l+r>>1; 18 if(x<=mid) insert(x,lc[rt],lc[fom],l,mid); 19 else insert(x,rc[rt],rc[fom],mid+1,r); 20 pushup(rt); 21 } 22 int queryl(int rt1,int rt2,int l,int r,int x){ 23 if(sum[rt1]==sum[rt2]) return -1; 24 if(l==r) return l; 25 int mid=l+r>>1; 26 if(x<=mid) return queryl(lc[rt1],lc[rt2],l,mid,x); 27 int tmp=queryl(rc[rt1],rc[rt2],mid+1,r,x); 28 return tmp==-1?queryl(lc[rt1],lc[rt2],l,mid,x):tmp; 29 } 30 int queryr(int rt1,int rt2,int l,int r,int x){ 31 if(sum[rt1]==sum[rt2]) return -1; 32 if(l==r) return l; 33 int mid=l+r>>1; 34 if(x>mid) return queryr(rc[rt1],rc[rt2],mid+1,r,x); 35 int tmp=queryr(lc[rt1],lc[rt2],l,mid,x); 36 return tmp==-1?queryr(rc[rt1],rc[rt2],mid+1,r,x):tmp; 37 } 38 }s; 39 inline int read(){ 40 int x=0,f=1; 41 char ch=getchar(); 42 while(ch<'0'||ch>'9'){ 43 if(ch=='-') f=-1; 44 ch=getchar(); 45 } 46 while(ch>='0'&&ch<='9'){ 47 x=(x<<1)+(x<<3)+(ch^48); 48 ch=getchar(); 49 } 50 return x*f; 51 } 52 void write(int x){ 53 if(x<0) putchar('-'), x=-x; 54 if(x>9) write(x/10); 55 putchar(x%10+'0'); 56 } 57 inline void add(int a,int b){ 58 to[++num]=b; nex[num]=head[a]; head[a]=num; 59 to[++num]=a; nex[num]=head[b]; head[b]=num; 60 } 61 void dfs1(int f,int s){ 62 fa[s]=f; dep[s]=dep[f]+1; siz[s]=1; 63 for(int i=head[s];i;i=nex[i]){ 64 int v=to[i]; 65 if(v==f) continue; 66 dfs1(s,v); 67 siz[s]+=siz[v]; 68 if(siz[v]>siz[son[s]]) son[s]=v; 69 } 70 } 71 void dfs2(int t,int s){ 72 dfn[s]=++cnt; id[cnt]=s; top[s]=t; 73 if(!son[s]) return; 74 dfs2(t,son[s]); 75 for(int i=head[s];i;i=nex[i]){ 76 int v=to[i]; 77 if(v!=fa[s]&&v!=son[s]) dfs2(v,v); 78 } 79 } 80 void dfs3(int st){ 81 s.insert(a[st],s.root[st],s.root[fa[st]],1,ext); 82 for(int i=head[st];i;i=nex[i]){ 83 int v=to[i]; 84 if(v==fa[st]) continue; 85 dfs3(v); 86 } 87 } 88 inline int LCA(int x,int y){ 89 int fx=top[x],fy=top[y]; 90 while(fx!=fy) 91 if(dep[fx]<dep[fy]) y=fa[fy], fy=top[y]; 92 else x=fa[fx], fx=top[x]; 93 return dep[x]<dep[y]?x:y; 94 } 95 void init(){ 96 sort(has+1,has+h+1); 97 ext=unique(has+1,has+h+1)-has-1; 98 for(int i=1;i<=n;i++) 99 a[i]=lower_bound(has+1,has+ext+1,a[i])-has; 100 for(int i=1;i<=q;i++) 101 R[i]=lower_bound(has+1,has+ext+1,R[i])-has; 102 } 103 int main(){ 104 n=read(); q=read(); type=read(); 105 for(int i=1;i<=n;i++) has[++h]=a[i]=read(); 106 for(int i=1;i<n;i++) add(read(),read()); 107 for(int i=1;i<=q;i++){ 108 R[i]=has[++h]=read(); k=read(); 109 for(int j=1;j<=k;j++) ask[i].push_back(read()); 110 } 111 init(); dfs1(0,1); dfs2(1,1); dfs3(1); 112 for(int i=1;i<=q;i++){ 113 for(int j=0;j<ask[i].size();j++) 114 ask[i][j]=(ask[i][j]-1+last*type)%n+1; 115 int lca=ask[i][0],ans=INT_MAX; 116 for(int j=1;j<ask[i].size();j++) lca=LCA(lca,ask[i][j]); 117 for(int j=0;j<ask[i].size();j++){ 118 int pre=s.queryl(s.root[ask[i][j]],s.root[fa[lca]],1,ext,R[i]); 119 int nex=s.queryr(s.root[ask[i][j]],s.root[fa[lca]],1,ext,R[i]); 120 cout<<(pre==-1?-1:has[pre])<<' '<<(nex==-1?-1:has[nex])<<endl; 121 if(pre!=-1) ans=min(ans,has[R[i]]-has[pre]); 122 if(nex!=-1) ans=min(ans,has[nex]-has[R[i]]); 123 } last=ans; 124 // write(ans); 125 putchar('\n'); 126 } 127 return 0; 128 }
T3 f
可恶。还没改出来。