NOI online 2022 游记

· · 个人记录

CQOI2022 rp++;

凯 旋 归 来

考试开始前一直进不去系统,发现自己进的是普及组,然后去世了。

正序开题
首先计划把 T1-T3 先全部看一遍,然后发现 T1 非常可做,

于是不往下看了。

Problem1 ~~题目名字也很好~~ 发现每个数据产生贡献,一定是在一个连续的区间里,然后想如果把这个区间修改就行了。 打着打着发现不太对,好像计算重复了,于是停了下来,~~想起之前在线很难的问题是怎么离线水掉的~~。 于是转而考虑离线,发现碰到区间的左端点看成修改,好像就能处理询问了。大概就是说在 $w_i$ 的位置让 $a_i$++,对于每一组询问 $(l,r)$在$l$位置查询$r$就行了,树状数组$O(nlogn)$查询。 ```cpp #include<bits/stdc++.h> using namespace std; typedef long long ll; //我悟了 const int N=5e5+5; int n,a[N],b[N],upd[N],l,r,q,cnt,ans[N]; int stk[N],top; int tr[N]; struct que{ int type;//2,1,0 int idx,r; int l,pos,t;//在pos加上t int ans; }query[N<<2]; bool cmp1(que a,que b) { if(a.l != b.l) return a.l < b.l; return a.type < b.type; } void modify(int l,int v) { for(int i=l;i<=n;i+= i &(-i)) tr[i] += v; } int check(int l) { int ans = 0; for(int i=l;i;i-= i & (-i)) ans += tr[i]; return ans; } inline void read(int &x) { char c = ' '; while(!isalnum(c)) c = getchar(); while(isalnum(c)) { x *= 10; x += c - '0'; c = getchar(); } } inline void print(int x) { int t = 0; int c[10]; while(x) { t++; c[t] = x % 10; x /= 10; } for(int i=t;i>=1;i--) putchar(c[i] + '0'); putchar('\n'); } int main() { freopen("stack.in","r",stdin); freopen("stack.out","w",stdout); read(n),read(q); for(int i=1;i<=n;i++) read(a[i]); for(int i=1;i<=n;i++) read(b[i]); for(int i=1;i<=n;i++) { while(top && (a[stk[top]] == a[i] || b[stk[top]] <= b[i])) top--; upd[i] = stk[top]; stk[++top] = i; //依葫芦画瓢 } for(int i=1;i<=n;i++) { query[++cnt] = {0,q+1,0,upd[i] + 1,i,1,0}; query[++cnt] = {2,q+1,0,i,i,-1,0}; } for(int i=1;i<=q;i++) { l = r = 0; read(l); read(r); query[++cnt] = {1,i,r,l,0,0,0}; } sort(query+1,query+cnt+1,cmp1); for(int i=1;i<=cnt;i++) { if(query[i].type == 1) ans[query[i].idx] = check(query[i].r); else modify(query[i].pos,query[i].t); } for(int i=1;i<=q;i++) print(ans[i]); return 0; } ``` ##### 花絮: 打完跑大样栗 $2.6s$,慌得一批。 + 快读,1.7s + 快写,1.001s(不做人了直接) + 大喊一声:万水千山总是情,少跑一秒行不行 + 想到一个卡常,改完后0.85s + 洛谷极限数据0.3s $Problem2

开始没什么思路,于是出去想了一会。

一看就是带负常数的$log$。 已知带负常数的做法只有两种:并查集,树状数组。 ~~由抽屉原理得~~,刚才用过树状数组,现在只能是并查集。 ~~就这么想出了正解~~ 大概就是把“会做题的集合”从小到大排序,把每个“集合”在并查集上合并起来。 如果发现额外合并了元素,那么就能知道是之前合并起来的,所以得知那个额外合并获得的地方就是那个“不重复的地方”,拿出来就是了。 ```cpp #include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e6+5; int T,n,k,tmp,flag,ans1,ans2; vector<int> vc[N]; //nlogn shui 1e6!!! int fa[N],sz[N],tub[N],fr[N];//并查集yyds int find(int x) { if(fa[x] == x) return x; return fa[x] = find(fa[x]); } inline void read(int &x) { // char c = ' '; // x = 0; // while(!isalnum(c)) c = getchar(); // while(isalnum(c)) // { // x *= 10; // x += c - '0'; // c = getchar(); // } scanf("%d",&x); } inline void print(int x) { int t = 0; int c[10]; while(x) { t++; c[t] = x % 10; x /= 10; } for(int i=t;i>=1;i--) putchar(c[i] + '0'); putchar('\n'); }//ssd yyds bool cmp(vector<int> a,vector<int> b) { return a.size() < b.size(); } int main() { freopen("discuss.in","r",stdin); freopen("discuss.out","w",stdout); cin>>T; while(T--) { ans1 = ans2 = 0; scanf("%d",&n); for(int i=1;i<=n;i++) vc[i].clear(); flag = false; for(int i=1;i<=n;i++) { vc[i].clear(); vc[i].push_back(i); scanf("%d",&k); for(int j=1;j<=k;j++) { scanf("%d",&tmp); vc[i].push_back(tmp); } } sort(vc+1,vc+n+1,cmp); for(int i=1;i<=n;i++) fa[i] = i,sz[i] = 1,tub[i] = 0,fr[i] = 0; for(int i=1;i<=n;i++) { if(vc[i].size() > 1) { tmp = find(vc[i][1]); fr[vc[i][1]] = i; } for(int j=2;j<(int)vc[i].size();j++) { int a = find(vc[i][j]);//合并合并!全部合并! fr[vc[i][j]] = i; if(a == tmp) continue; fa[a] = tmp; sz[tmp] += sz[a]; } if((vc[i].size() > 1) && sz[tmp] != ((int)vc[i].size())- 1) { flag = true; ans1 = i; break; } } if(!flag) puts("NO"); else { puts("YES"); for(int i=1;i<(int)vc[ans1].size();i++) { tub[vc[ans1][i]] = true; //cout<<vc[ans1][i]<<endl; } for(int i=1;i<=n;i++) { if(find(i) == tmp && !tub[i]) ans2 = fr[i]; } printf("%d ",vc[ans1][0]); print(vc[ans2][0]); } } return 0; } ``` ------------ 写完还有$90min

测大样栗的时候死活RE,检查了半天发现是输入错了,再检查:???????这这不对吧是谁要陷害我?€€£你要陷害我是不是?
《于是调了90min输入》
11:59无可奈何地交了依旧RE的代码。

前方高能 前方高能 前方高能 非战斗人员请迅速撤离

考完马上知道:大样栗锅了!
我那胎死腹中的T3
拿着新来的大样栗测一测,马上就AC了。
@CCF_NOI讨说法

花絮2

1:15知道洛谷有冥间数据。测T2时非常自信的大喊了一声:我不开O2!

真香。

巨佬们的情况

@L_h_写出T1,文件操作写错了
@tanyulin主席树写出T1(orz!)加上骗分有130。自测发现UB了,默哀。
@duanyixiu炸掉了;
@yanghanyv的主席树顺利通关,orz!
@Sheng_horizon不仅T1和我想的一样,还自创了丹钓战的新写法,orz!
@MichaelLee的倍增大家都没懂,但是他也过了T1,orz!
Chery自然是AK了()

但是 @Sword_K炸了,,,
默哀。

冲进前25%!好像完全没有问题

upd on 3/31/2022

出分了,没挂分,CCF nb,希望 CQYZ 以后还能再次辉煌。