1. 程式人生 > >codeforces#475 div1

codeforces#475 div1

src 最小 can clas i++ ID swa 連接 mes

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