您的位置:首页 > 其它

ZF_20160704_CF15X

2016-07-04 22:55 295 查看
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的食物。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: