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;
}
View Code

 

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;
}
View Code

 

 

 

以上是关于codeforces#475 div1的主要内容,如果未能解决你的问题,请参考以下文章

[Codeforces 475B] Strongly Connected City

Codeforces475D - CGCDSSQ

Codeforces 475D CGCDSSQ 区间gcd值

Codeforces Round #475 (Div. 2) D. Destruction of a Tree

Codeforces Round #475 (Div. 2) C - Alternating Sum

代码源 Div1#104no crossing,Codeforces 793D,2100分,区间dp