240117 lxl省选模拟

省流:\(66 + 100 + 50\)。蓝紫黑。T1 6人过,T2 20人过,成分复杂。

T1

原题:P6571。

题解:感性理解题目中的性质,其中一个是答案 \(\leq k\),还有一个是我们一定可以找到一种给边定向的方案,使得每个点出度 \(\leq k\),构造方案具体可以每次找出度数最小的点,将与这个点相连且还没定向过的边都定为出边,并更新连向的点的度数。找到定向方案以后就可以枚举一个点,\(2^k\) 枚举最大团中的点,最后 \(\Theta(k)\) check 一下就行。时间复杂度 \(O(nk2^k)\)

代码:

#include<bits/stdc++.h> using namespace std; const int N=50005; vector<int> g[N]; unordered_map<int,int> mp[N]; int n,k,deg[N],vis[N],s[N],ans=0; struct node { int x,y; bool operator<(const node &o) const {return y>o.y;} };priority_queue<node> pq; int main() { cin>>n>>k; for(int i=1; i<=n; i++) { int p;cin>>p; for(int j=1; j<=p; j++) { int x;cin>>x; g[i].push_back(x+1); mp[i][x+1]; } deg[i]=g[i].size(); } for(int i=1; i<=n; i++) pq.push((node){i,deg[i]}); while(!pq.empty()) { int u=pq.top().x; pq.pop(); if(vis[u]) continue; vis[u]=true; vector<int> ve; for(auto v:g[u]) if(!vis[v]) { ve.push_back(v); deg[v]--; pq.push((node){v,deg[v]}); } for(int i=0; i<ve.size(); i++) s[i]=0; for(int i=0; i<ve.size(); i++) for(int j=0; j<ve.size(); j++) if(mp[ve[i]].count(ve[j])) s[i]|=(1<<j); for(int i=0; i<ve.size(); i++) s[i]|=(1<<i); for(int i=0; i<(1<<ve.size()); i++) { bool flag=true; for(int j=0; j<ve.size(); j++) if(i&(1<<j-1)) flag&=((s[j]&i)==i); if(flag) ans=max(ans,__builtin_popcount(i)+1); } } cout<<ans<<"\n"; return 0; }

闲话:考场上不了解最大团的复杂度,直接写了个板子上去就跑路了,时间复杂度貌似是 \(\Theta(rand())\)

T2

原题:P9991。

容易把题目转化为对于每一种颜色,把这个颜色去掉,求 \([l,r]\) 的最长连续段的最大值,把连续段分为三部分,第一部分为左端点到第一个这个颜色, 第二部分为右端点到最后一个这个颜色,第三部分为两个这个颜色中间的段。前两个部分可以用类似区间数颜色单 log 做法,只保留第一个/最后一个同种颜色的,容易用线段树二分做到单 log,第三部分依然考虑扫描线,右端点向右移动,设新增的颜色上一个位置为 \(lst\),那么对于左端点在 \([1,lst]\) 之间的询问,答案会与这个段长度取 max,于是只需要实现一个区间取 max,单点查询的数据结构即可,好像要写吉司机?发现是单点查询所以直接暴力下传 tag 或者标记永久化即可。

时间复杂度 \(O(n \log n)\)

代码:

#include<bits/stdc++.h> using namespace std; namespace IO { constexpr int S = (1 << 21); int digital = 2; bool is_round = 1; char b[S], *m = b, *n = b, g[S], *p = g; inline void f() { fwrite(g, 1, p - g, stdout), p = g; } struct R { inline bool w(char c) { return 47 < c && c < 58; } inline bool y(char c) { return c == ' ' || c == '\n' || c == '\r' || c == '\t'; } inline char i() { if (m == n) n = (m = b) + fread(b, 1, S, stdin); return m == n ? ' ' : *m++; } template <class T> inline R &operator>>(T &x) { char c = i(); T f = 1; for (x = 0; !w(c);) { if(c == '-') f = -1; c = i(); } while (w(c)) x *= 10, x += c ^ 48, c = i(); x *= f; return *this; } inline R &operator>>(char *s) { int l = 0; char c; operator>>(c); for (; !y(c); s[l++] = c, c = i()) ; s[l] = '\0'; return *this; } inline R &operator>>(string &s) { s = ""; char c = i(); while(y(c)) c = i(); while(!y(c)) s += c, c = i(); return *this; } inline R &operator>>(double &x) { double t = 1, s = 0; char c = i(); for (x = 0; !w(c); c = i()) s = (c == '-'); for (; w(c); c = i()) x = x * 10 + c - 48; if (c == '.') for (c = i(); w(c); c = i()) x += (t /= 10.0) * (c - 48), s && (x = -x); return *this; } inline R &operator>>(char &c) { do c = i(); while (y(c)); return *this; } template<class T> void tie(T x) {} } cin; #define endl '\n' struct W { inline void o(char c) { *p++ = c; if (p - g == S) f(); } template <class T> inline W &operator<<(T x) { if (!x) return o(48), *this; if(x < 0) o('-'), x = -x; static int s[64], t = 0; while (x) s[++t] = x % 10, x /= 10; while (t) o(s[t--] + 48); return *this; } inline W &operator<<(char c) { o(c); return *this; } template <class T> inline W &operator<<(T *s) { int c = 0; while (s[c]) o(s[c++]); return *this; } inline W &operator<<(double x) { int k = 0; if(x < 0) o('-'), x = -x; if(is_round) x += 5 * pow(10, -digital - 1); operator<<((int)x), o('.'), x -= (int)x; while (k++ < digital) o((int)(x *= 10) + 48), x -= (int)x; return *this; } inline W &operator<<(string s) { for(int i = 0; s[i] ^ '\0'; ++i) o(s[i]); return *this; } template<class T> void tie(T x) {} ~W() { f(); } } cout; struct E { template <class T> E &operator<<(T x) { return *this; } } cerr; } ; #define cin IO::cin #define cout IO::cout const int N=2e6+5; vector<int> ve[N]; int n,m,a[N],lst[N],ans[N]; struct node {int l,r,id;}q[N]; struct segtree { int L[N<<2],R[N<<2],val[N<<2]; void build_tree(int l,int r,int id=1) { L[id]=l,R[id]=r,val[id]=0; if(l==r) return; int mid=l+r>>1; build_tree(l,mid,id<<1),build_tree(mid+1,r,id<<1|1); } void add(int x,int y,int id=1) { if(L[id]==x&&R[id]==x) { val[id]+=y; return; } int mid=L[id]+R[id]>>1; if(x<=mid) add(x,y,id<<1); else add(x,y,id<<1|1); val[id]=val[id<<1]+val[id<<1|1]; } int mn(int id) { if(!val[id]) return 0; if(L[id]==R[id]) return L[id]; if(val[id<<1]) return mn(id<<1); else return mn(id<<1|1); } int mx(int id) { if(!val[id]) return 0; if(L[id]==R[id]) return L[id]; if(val[id<<1|1]) return mx(id<<1|1); else return mx(id<<1); } int querymn(int l,int r,int id=1) { if(L[id]>=l&&R[id]<=r) return mn(id); int mid=L[id]+R[id]>>1,ans=0; if(l<=mid) ans=querymn(l,r,id<<1); if(r>mid&&!ans) ans=querymn(l,r,id<<1|1); return ans; } int querymx(int l,int r,int id=1) { if(L[id]>=l&&R[id]<=r) return mx(id); int mid=L[id]+R[id]>>1,ans=0; if(r>mid) ans=querymx(l,r,id<<1|1); if(l<=mid&&!ans) ans=querymx(l,r,id<<1); return ans; } }t1,t2; struct ibengbuzhu { int L[N<<2],R[N<<2],tag[N<<2]; void build_tree(int l,int r,int id=1) { L[id]=l,R[id]=r,tag[id]=0; if(l==r) return; int mid=l+r>>1; build_tree(l,mid,id<<1),build_tree(mid+1,r,id<<1|1); } void modify(int l,int r,int x,int id=1) { if(L[id]>=l&&R[id]<=r) { tag[id]=max(tag[id],x); return; } int mid=L[id]+R[id]>>1; if(l<=mid) modify(l,r,x,id<<1); if(r>mid) modify(l,r,x,id<<1|1); } int query(int x,int id=1) { if(L[id]==R[id]) return tag[id]; int mid=L[id]+R[id]>>1; if(x<=mid) return max(tag[id],query(x,id<<1)); else return max(tag[id],query(x,id<<1|1)); } }t3; int main() { cin>>n>>m; for(int i=1; i<=n; i++) cin>>a[i]; for(int i=1; i<=m; i++) cin>>q[i].l>>q[i].r,q[i].id=i; t1.build_tree(1,n),t2.build_tree(1,n),t3.build_tree(1,n); for(int i=1; i<=m; i++) ve[q[i].r].push_back(i); for(int i=1; i<=n; i++) { if(lst[a[i]]) t1.add(lst[a[i]],-1),t3.modify(1,lst[a[i]],i-lst[a[i]]-1); t1.add(i,1),lst[a[i]]=i; for(int j=0; j<ve[i].size(); j++) ans[q[ve[i][j]].id]=max(ans[q[ve[i][j]].id],max(q[ve[i][j]].r-t1.querymn(q[ve[i][j]].l,q[ve[i][j]].r),t3.query(q[ve[i][j]].l))); } for(int i=1; i<=m; i++) ve[q[i].r].clear(); for(int i=1; i<=n; i++) lst[a[i]]=0; for(int i=1; i<=m; i++) ve[q[i].l].push_back(i); for(int i=n; i>=1; i--) { if(lst[a[i]]) t2.add(lst[a[i]],-1); t2.add(i,1),lst[a[i]]=i; for(int j=0; j<ve[i].size(); j++) ans[q[ve[i][j]].id]=max(ans[q[ve[i][j]].id],t2.querymx(q[ve[i][j]].l,q[ve[i][j]].r)-q[ve[i][j]].l); } for(int i=1; i<=m; i++) cout<<ans[i]<<"\n"; return 0; }

闲话:原题极其卡常,模拟赛能过完全是因为时限多开了 2s/kx。

T3

原题:P9996。

还不会。


__EOF__

本文作者System_Error
本文链接https://www.cnblogs.com/System-Error/p/18677027.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   System_Error  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
点击右上角即可分享
微信分享提示