codeforces#475 div1
Posted allvphx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codeforces#475 div1相关的知识,希望对你有一定的参考价值。
B.
非常有意思的题目,但一开始没有想出来怎么证明。有点偏向于离散数学证明题。
首先给出结论:当且仅当点的个数为奇数时可以构造出来一种删除序列。
首先考虑证明必要性,每次删除操作相当于在原先的树上咔去偶数条边,从而必然有点的个数为奇数。
考虑充分性,我们从深度较大的点到深度较小的点删除,每次对于一个点x,我们要么能将其子树删完,要么剩余一个联通的度数全都是奇数的子树,必然可以通过上面的点删除完。
这样归纳到最后必然有形成的要么是一个度数全为奇数的树,要么能删空。
而对于一个度数全为奇数的树,从一个点开始,归纳法:
一个可以删空的子树如果根的初始度数为奇数,则必然是连接到奇数个可删空子树,有偶数*奇数 = 奇数个初始度数为偶数的点。
另外三种情况同上,最终证明一个子树能删空 <=> 其中有奇数个初始度数为偶数的点。
而对于一个有奇数个点的树,度数为偶数的点必然有奇数个。
得证。(貌似证麻烦了)
const int N = 200010; vector<int> g[N],g2[N]; int n, root, dep[N], d[N], ans[N], tot, fa[N]; bool del[N]; struct node { int x; bool operator < (const node &tmp) const { if(dep[x]!=dep[tmp.x]) return dep[x] > dep[tmp.x]; else return x < tmp.x; } }; set<node> St; void dfs(int x) { for(auto p:g[x]) { dep[p] = dep[x]+1; dfs(p); } } int main() { cin >> n; FOR(i,1,n) { scanf("%d",&fa[i]); if(fa[i] == 0) root = i; else g[fa[i]].pb(i), d[i]++, d[fa[i]]++; } dfs(root); FOR(i,1,n) if(d[i]%2==0) St.insert((node){i}); FOR(i,1,n) if(fa[i]) g[i].pb(fa[i]); while(!St.empty()) { int x = St.begin()->x; del[x] = 1; ans[++tot] = x; St.erase(St.begin()); for(auto p:g[x]) if(!del[p]){ if(--d[p]%2==0) St.insert((node){p}); else St.erase((node){p}); } } if(tot < n) cout << "NO" << endl; else { cout << "YES" << endl; FOR(i,1,tot) printf("%d\n",ans[i]); } return 0; }
C.
可以注意到对于任意一种初始矩形,我们只需要确认横向切几道,纵向切几道,就可以确认初始矩形的大小。
对于任意一种切分方案,我们都可以通过调整将其变为如下方案:
D.
考虑只有 $\sqrt n$ 种不同的长度,并且有各个询问串不同使得,如果我们采用 $O(当前字符出现次数)$ 的方法求最小长度,均摊下来复杂度 $O(n \sqrt n)$
问题在于求解出每个字符出现的位置,AC自动机上建出fail树,而后启发式合并即可。
$O(n \sqrt n + n log^2n)$
关键在于分析复杂度。
#include <bits/stdc++.h> using namespace std; #define all(x) (x).begin(),(x).end() #define se second #define fi first #define debug(x) cerr << #x << " = " << x << endl; #define rep(i,s,t) for(int i=(s);i<=(t);i++) #define rrep(i,s,t) for(int i=(s);i>=(t);i--) #define SZ(x) ((int)(x).size()) #define pb push_back #define mp make_pair typedef pair<int,int> PII; typedef long long ll; const int mo = 1000000007; ll powmod(ll x,ll n) {ll re=1; for(;n;n>>=1,x=x*x%mo) if(n&1) re=re*x%mo; return re; } ll gcd(ll a,ll b) {return b? gcd(b,a%b):a;} //head const int N = 100000 + 10; struct node { node *ch[26],*fa; vector<PII> q; int id; }pool[N],*cur=pool,*rt=&pool[0]; int n,m,nps,ans[N],len[N]; char s[N],tp[N]; vector<int> g[N],vc[N]; void add(char *c,int id,int mi) { node *p = rt; while(*c!=‘\0‘) { if(!p->ch[*c-‘a‘]) p->ch[*c-‘a‘] = ++cur; p = p->ch[*c-‘a‘]; c++; } p->q.pb(mp(id,mi)); } queue<node*> q; void getfail() { q.push(rt); rt->fa = rt; for(auto i=&pool[0];i<=cur;i++) i->id = ++nps; while(!q.empty()) { node *p = q.front(); q.pop(); if(p->fa != p) g[p->fa->id].pb(p->id); rep(i,0,25) { if(p->ch[i]) { if(p!=rt) p->ch[i]->fa = p->fa->ch[i]; else p->ch[i]->fa = rt; q.push(p->ch[i]); } else { if(p!=rt) p->ch[i] = p->fa->ch[i]; else p->ch[i] = rt; } } } } set<int> son[N]; void dfs(int x,set<int>* &ch) { set<int> *ss = &son[x]; ch->clear(); for(auto p:vc[x]) ch->insert(p); for(auto p:g[x]) { ss->clear(); dfs(p,ss); if(ss->size() > ch->size()) swap(ss,ch); for(auto j=ss->begin();j!=ss->end();j++) ch->insert(*j); } if(!pool[x-1].q.empty()) { auto tt = pool[x-1].q.begin(); if(tt->se > (int)ch->size()) ans[tt->fi] = -1; else { ans[tt->fi] = n; vector<int> q; for(auto j=ch->begin();j!=ch->end();j++) q.pb(*j); rep(i,0,SZ(q)-tt->se) { ans[tt->fi] = min(ans[tt->fi], q[i+tt->se-1]-q[i]+len[tt->fi]); } } } } set<int> trp; int main() { int q,t; scanf("%s",s+1); n = strlen(s+1); scanf("%d",&q); rep(i,1,q) { scanf("%d%s",&t,tp); len[i] = strlen(tp); add(tp,i,t); } getfail(); node *tmp = rt; rep(i,1,n) { tmp = tmp->ch[s[i]-‘a‘]; vc[tmp->id].pb(i); } set<int> *tt = &son[0]; dfs(1,tt); rep(i,1,q) printf("%d\n",ans[i]); return 0; }
以上是关于codeforces#475 div1的主要内容,如果未能解决你的问题,请参考以下文章
[Codeforces 475B] Strongly Connected City
Codeforces 475D CGCDSSQ 区间gcd值
Codeforces Round #475 (Div. 2) D. Destruction of a Tree