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 }
T1
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 }
T2JYFHYX的代码
但一般人显然没有那种毅力。学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 }
T2zxs的zxs做法
T3 f
可恶。还没改出来。
2021.7.21考试总结[NOIP模拟22]的更多相关文章
- 2021.8.21考试总结[NOIP模拟45]
T1 打表 由归纳法可以发现其实就是所有情况的总和. $\frac{\sum_{j=1}^{1<<k}(v_j-v_{ans})}{2^k}$ $code:$ 1 #include< ...
- 2021.9.21考试总结[NOIP模拟58]
T1 lesson5! 开始以为是个无向图,直接不懂,跳去T2了. 之后有看了一眼发现可暴力,于是有了\(80pts\). 发现这个图是有拓扑序的,于是可以用拓扑排序找最长路径.先找原图内在最长路径上 ...
- 2021.9.17考试总结[NOIP模拟55]
有的考试表面上自称NOIP模拟,背地里却是绍兴一中NOI模拟 吓得我直接文件打错 T1 Skip 设状态$f_i$为最后一次选$i$在$i$时的最优解.有$f_i=max_{j<i}[f_j+a ...
- 2021.8.11考试总结[NOIP模拟36]
T1 Dove玩扑克 考场并查集加树状数组加桶期望$65pts$实际$80pts$,考后多开个数组记哪些数出现过,只扫出现过的数就切了.用$set$维护可以把被删没的数去掉,更快. $code:$ 1 ...
- [考试总结]noip模拟22
又发现模拟 \(22\) 的总结也咕掉了,现在补上它... 似乎又是gg的一场. 以为自己的部分分数打的很全,然而到后面发现自己的树剖打假了 \(\color{green}{\huge{\text{树 ...
- 2021.8.19考试总结[NOIP模拟44]
T1 emotional flutter 把脚长合到黑条中. 每个黑条可以映射到统一区间,实际操作就是左右端点取模.长度大于$k$时显然不合法. 然后检查一遍区间内有没有不被黑条覆盖的点即可. 区间端 ...
- 2021.7.28考试总结[NOIP模拟26]
罕见的又改完了. T1 神炎皇 吸取昨天三个出规律的教训,开场打完T2 20pts直接大力打表1h. 但怎么说呢,我不懂欧拉函数.(其实exgcd都忘了 于是只看出最大平方因子,不得不线性筛,爆拿60 ...
- 2021.7.27考试总结[NOIP模拟25]
罕见的改完了题 T1 random 一堆概率,一堆函数,一堆递归,一眼不可做, 但它只有一个参数,所以.. 熠神本着"只有20太难看"的心态,通过样例三个出规律,口胡了一波$\fr ...
- 2021.6.17考试总结[NOIP模拟8]
T1 星际旅行 其实就是求两条只走一遍的边的方案数. 考场上第一眼就感觉不可做,后来画了几个图,发现好像只要两个边是相连的就可以只走一遍,居然还真拿了30.. 其实是一道欧拉路的题,把每条非自环的边看 ...
随机推荐
- 硕盟SM-T54|type-c转接头HDMI+VGA+USB3.0+PD3.0四合一多功能扩展坞接口功能说明
硕盟SM-T54是一款 TYPE C转HDMI+VGA+USB3.0+PD3.0四合一多功能扩展坞,支持四口同时使用,您可以将含有USB 3.1协议的电脑主机,通过此产品连接到具有HDMI或VGA的显 ...
- linux停止进程
$ kill -QUIT 主进程号 例如:kill -QUIT 1708 这种方式相对来说会有一个停止的过程,先将子进程停止掉,然后再停掉主进程. 快速停止Nginx: $ kill -TERM 主进 ...
- jquery .play()报错is not a function
报错原因:play()方法属于DOM对象方法,$('#audio')为jquery对象解决办法:将jquery对象转换为DOM对象首先打印jquery对象$('#audio') 两种转换方式将一个jQ ...
- Java面向对象系列(3)- 回顾方法的调用
方法的调用 静态方法 非静态方法 形参和实参 值传递和引用传递 this关键字(继承篇讲解) 静态方法 非静态方法 形参和实参 package oop.demo01; public class Dem ...
- Java基础系列(37)- 数组下标越界及小结
数组的四个基本特点 其长度是确定的,数组一旦被创建,它的大小就是不可以改变的 其元素必须是相同类型,不允许出现混合类型 数组中的元素可以是任何数据类型,包括基本类型和引用类型 数组变量属于引用类型,数 ...
- Nginx系列(1)- Nginx简介
公司产品出现瓶颈 公司项目刚上线的时候,并发量小,用户使用少,所以在低并发的情况下,一个jar包启动应用就够了,然后内部tomcat返回内容给用户 但是慢慢的,使用平台的用户越来越多,并发量慢慢增大了 ...
- Shell系列(3)- 命令别名
前言 使用alias命令创建命令别名,是Bash的一个基本功能:别名有两种形式,一种暂时的,Linux重启后失效.另外一种永久的通过该配置文件实现 使用更改别名 临时 命令格式:alias 别名='原 ...
- 显式等待until传入自定义方法
WebDriverWait(driver,10).until(expected_conditions.element_to_be_clickable(ele)) 通过追踪代码,可以发现上面的eleme ...
- ul li 标签
去除制表符: li{ list-style:none; } ul{ /* 靠左*/ padding-left: 5px; }
- P3211-[HNOI2011]XOR和路径【高斯消元】
正题 题目链接:https://www.luogu.com.cn/problem/P3211 题目大意 一个\(n\)个点\(m\)条边的无向图,从\(1\)到\(n\)随机游走.求期望路径异或和. ...