ZF_20160704_CF15X

来源:互联网 发布:泰安飞讯网络怎么样 编辑:程序博客网 时间:2024/06/05 20:30

246E
树上每个节点对应一个字符串,指定子树和深度,求不同字符串个数。
STL解决。

#include<cstdio>#include<cstring>#include<algorithm>#include<map>#include<set>#include<vector>#include<utility>#include<string>using namespace std;const int _=200010;int n,m;char c[_][33];namespace G{    int dep[_],dfn[_],lea[_],step;    vector<int>V[_];    vector<pair<int,int> >Pt[_];    map<pair<int,int>,int>M;    set<string>S;    void dfs(int u,int f,int d)    {        dfn[u]=++step;        Pt[d].push_back(make_pair(step,u));        dep[u]=d;        int len=V[u].size();        for(int i=0;i<len;i++)        {            int v=V[u][i];            dfs(v,u,d+1);        }        lea[u]=++step;    }    int get(int v,int k)    {        if(M[make_pair(v,k)])return M[make_pair(v,k)]-1;        S.clear();        vector<pair<int,int> >::iterator        l=lower_bound(Pt[dep[v]+k].begin(),Pt[dep[v]+k].end(),make_pair(dfn[v],_)),        r=lower_bound(Pt[dep[v]+k].begin(),Pt[dep[v]+k].end(),make_pair(lea[v],_));        for(vector<pair<int,int> >::iterator ir=l;ir!=r;ir++)            S.insert(string(c[ir->second]+1));        return (M[make_pair(v,k)]=S.size()+1)-1;    }    int Go()    {        while(~scanf("%d",&n))        {            for(int i=0;i<=n;i++)V[i].clear(),Pt[i].clear();            M.clear();S.clear();            for(int i=1;i<=n;i++)            {                int x;                scanf("%s%d",c[i]+1,&x);                V[x].push_back(i);            }            step=0;            dfs(0,-1,1);            scanf("%d",&m);            while(m--)            {                int v,k;                scanf("%d%d",&v,&k);                printf("%d\n",get(v,k));            }        }    }}int main(){    G::Go();}

248D
一条街n个点,shop可买一块糖,给每个home送去一块糖,在时间限制t的前提下,求初始时带的糖的最小值。
对答案进行二分。

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int dat[500010],n,m,num[500010],t,last,o;char c[500010];bool OK(int mid){    int tmp=1e9,res=0;    num[0]=mid;    m=last;//最后一个 home    for(int i=1;i<=n;++i)    {        num[i]=num[i-1]+dat[i];        if(num[i]==0 && num[i-1]==-1)m=max(m,i);    }    if(m==0)return 1;//没有home    for(int i=1;i<=m;++i)    {        res++;        if(num[i-1]==0 && num[i]==-1)        {            o=i;            tmp=min(tmp,res+(m-i)*2);        }        if(num[i-1]==-1 && num[i]==0)        {            res+=(i-o)*2;        }    }    tmp=min(tmp,res);    return tmp<=t;}int main(){    while(~scanf("%d%d%s",&n,&t,c+1))    {        for(int i=1;i<=n;++i)dat[i]=c[i]=='H'?-1:c[i]=='S'?1:0;        int l=0,r=0;        for(int i=1;i<=n;++i)        {            if(dat[i]==-1)r++,last=i;            if(dat[i]==1)l--;        }        l+=r;        if(l<0)l=0;//shop 多        if(last>t){ puts("-1");continue; }        while(l<r)        {            int mid=(l+r)/2;            if(OK(mid)) r=mid;            else l=mid+1;        }        printf("%d\n",r);    }}

248E
f[u][i]u点有i个未用过的概率。

254E
f[i][j]第i天剩下j的食物。

0 0