牛客网round1

题解:

1.

二分答案之后判断

把式子移项使得x,y不关联

#include  <bits/stdc++.h>
using namespace std;
#define rint register int
#define IL inline
#define rep(i,h,t) for (rint i=h;i<=t;i++)
#define dep(i,t,h) for (rint i=t;i>=h;i--)
const int N=3e5;
int a[N],sum[N],n,m;
const int INF=1e9;
bool check(int x)
{
  sum[0]=0;
  int mina=-INF;
  rep(i,1,n)
  {
    if (a[i]<x) sum[i]=sum[i-1]+1; else sum[i]=sum[i-1];
    if (i-m+1>0) mina=max(mina,2*sum[i-m]-(i-m+1));
    if (2*sum[i]-i<=mina) return(1);
  }
  return(0);
}
int main()
{
  freopen("1.in","r",stdin);
  freopen("1.out","w",stdout);
  ios::sync_with_stdio(false);
  cin>>n>>m;
  rep(i,1,n) cin>>a[i];
  int h=0,t=INF;
  while (h<t)
  {
    int mid=(h+t+1)>>1;
    if (check(mid)) h=mid; else t=mid-1;
  }
  cout<<h<<endl;
  return 0;
}

 

2.

数位dp

考虑10个数字一共有18个

C(27,9) 算一下发现不大

然后就直接记忆化搜索就行了

数比较大可以用map记录

但好像比较慢于是改了hash

然后有3个点是考细节的

后面两个是map如果初值为0就炸了 可能之后一直为0 因为y可以是-1

另外一个是0要特殊考虑dfs(0)

#include <bits/stdc++.h>
using namespace std;
#define rint register int
#define IL inline
#define rep(i,h,t) for (rint i=h;i<=t;i++)
#define dep(i,t,h) for (rint i=t;i>=h;i--) 
#define ll long long
#define mp(x,y) make_pair(x,y)
ll l,n,m,f[100];
int cnt=0;
const int mo=6e6+7;
struct re{
  bool a,b;
  short c; 
  ll d,ans;
}hs[mo+1000];
queue<int> q; 
struct hash{
  ll find(bool a,bool b,short x,ll y)
  {
    int t1=((1ll*x%mo*y%mo)%mo+mo)%mo;
    while (hs[t1].c&&!(hs[t1].a==a&&hs[t1].b==b&&hs[t1].c==x&&hs[t1].d==y))
      t1++,cnt++;
    if (hs[t1].c) return(hs[t1].ans);
    return(-1);
  }
  void insert(bool a,bool b,short x,ll y,ll ans)
  {
    int t1=((1ll*x%mo*y%mo)%mo+mo)%mo;
    while (hs[t1].c) t1++,cnt++;
    hs[t1].a=a; hs[t1].b=b; hs[t1].c=x; hs[t1].d=y; hs[t1].ans=ans;
    q.push(t1);
  }
  void clear()
  {
    while (!q.empty())
    {
      int x=q.front(); q.pop();
      hs[x].c=hs[x].ans=0;
    }
  }
}M;
ll dfs(short x,ll y,bool z,bool kk)
{
  cnt++;
  ll ans1=M.find(z,kk,x,y);
  if (ans1!=-1) return(ans1);
  if (x==l+1)
  {
    if (kk==1) y=0;
    if (y<=m)
    {
      return(1);
    }
    return(0);
  }
  ll ans=0;
  rep(i,0,9)
  if (i==0&&kk==1) ans+=dfs(x+1,1,0,1);
  else
  {
    if (z==1)
    {
      if (i<f[x]) ans+=dfs(x+1,y*i,0,0);
      if (f[x]==i) ans+=dfs(x+1,y*i,1,0);
    } else ans+=dfs(x+1,y*i,0,0);
  }
  M.insert(z,kk,x,y,ans);
  return(ans);
}
ll js(ll x,ll y)
{
  if (x<0) return(0);
  M.clear();
  ll tmp=x; l=0;
  if (x==0) l=1,f[1]=0;
  while (tmp) l++,f[l]=tmp%10,tmp/=10;
  reverse(f+1,f+l+1);
  m=y;
  return dfs(1,1,1,1);
}
int main()
{
  ios::sync_with_stdio(false);
  ll x1,x2,y1,y2;
  cin>>x1>>x2>>y1>>y2;
  cout<<js(x2,y2)
  -js(x2,y1-1)-
  (js(x1-1,y2)-
  js(x1-1,y1-1))<<endl;
  return 0; 
}

 

3.

大体思路就是差分来做

刚开始傻逼的写了直接dfs拿线段树来维护。。

这样显然是有问题的。。。

并且,我的树上二分也很傻比。。。

取了比它深度浅的二分所以既要多写代码又要多写细节。。

拍完了细节才发现要改成线段树合并

5min改完就a了。。

另外一种做法是主席树+二分 二分部分和这种做法一样

主席树就是维护dfs序也和这个基本一样

利用相减表示出当前子树

#include <bits/stdc++.h>
using namespace std;
#define rint register int
#define IL inline
#define rep(i,h,t) for (rint i=h;i<=t;i++)
#define dep(i,t,h) for (rint i=t;i>=h;i--)
#define mid ((h+t)>>1)
const int N=3e5;
int head[N],l,dep[N],bz[N][20],ans[N];
vector<int> ve[N],ve3[N];
struct re{
  int a,b;
}a[N*2];
vector<re> ve2[N];
void arr(int x,int y)
{
  a[++l].a=head[x];
  a[l].b=y;
  head[x]=l;
}
void dfs(int x,int y)
{
  bz[x][0]=y; dep[x]=dep[y]+1;
  for (rint u=head[x];u;u=a[u].a)
  {
    rint v=a[u].b;
    if (v!=y) dfs(v,x);
  }
}
int lca(int x,int y)
{
  if (dep[x]<dep[y]) swap(x,y);
  dep(i,19,0) if (dep[bz[x][i]]>=dep[y]) x=bz[x][i];
  if (x==y) return(x);
  dep(i,19,0) if (bz[x][i]!=bz[y][i]) x=bz[x][i],y=bz[y][i];
  return(bz[x][0]); 
}
int f[N],ph[N],pt[N],num,n,m,root[N];
struct sgt{
  int v[N*20],ls[N*20],rs[N*20],cnt;
  #define updata(x) v[x]=v[ls[x]]+v[rs[x]]
  void change(int &x,int h,int t,int pos,int k)
  {
    if (pos<=0) return;
    if (!x) x=++cnt;
    if (h==t)
    {
      v[x]+=k; return;
    }
    if (pos<=mid) change(ls[x],h,mid,pos,k);
    else change(rs[x],mid+1,t,pos,k);
    updata(x);
  }
  int query(int x,int h,int t,int h1,int t1)
  {
    if (h1<=h&&t<=t1) return(v[x]);
    int ans=0;
    if (h1<=mid) ans+=query(ls[x],h,mid,h1,t1);
    if (mid<t1) ans+=query(rs[x],mid+1,t,h1,t1);
    return(ans); 
  }
  void find(int x,int h,int t,int h1,int t1)
  {
    if (h1<=h&&t<=t1)
    {
      f[++num]=x; ph[num]=h; pt[num]=t;
      return;
    }
    if (h1<=mid) find(ls[x],h,mid,h1,t1);
    if (mid<t1) find(rs[x],mid+1,t,h1,t1);
  }
  int find2(int x,int h,int t,int k)
  {
    if (h==t)
    {
      if (v[x]>=k) return(h);
      else return(h+1);
    } 
    if (v[rs[x]]<k) return(find2(rs[x],mid+1,t,k));
    else return(find2(ls[x],h,mid,k-v[rs[x]]));
  }
  int query2(int kk,int x,int y)
  {
    int k1=y-query(kk,1,n,dep[x]+1,n);
    num=0; find(kk,1,n,1,dep[x]);
    dep(i,num,1)
    {
      if (v[f[i]]>=k1) k1-=v[f[i]];
      else return(find2(f[i],ph[i],pt[i],k1));
    }
    return(1);
  }
  int merge(int x,int y)
  {
    if (!x||!y) return(x|y);
    v[x]+=v[y];
    ls[x]=merge(ls[x],ls[y]);
    rs[x]=merge(rs[x],rs[y]);
    return(x);
  }
}S;
void dfs2(int x,int y)
{
  for (rint u=head[x];u;u=a[u].a)
  {
    rint v=a[u].b;
    if (v!=y) dfs2(v,x),root[x]=S.merge(root[x],root[v]);
  }
  int l=(int)(ve3[x].size())-1;
  rep(i,0,l)
  {
    S.change(root[x],1,n,dep[x],1);
    S.change(root[x],1,n,dep[ve3[x][i]]-1,-1);
  }
  l=(int)(ve2[x].size())-1;
  rep(i,0,l)
  {
    int x1=ve2[x][i].a,y1=ve2[x][i].b;
    ans[x1]=dep[x]-S.query2(root[x],x,y1);
  }
  l=(int)(ve[x].size())-1;
  rep(i,0,l)
  {
    S.change(root[x],1,n,dep[x]-1,1);
    S.change(root[x],1,n,dep[ve[x][i]],-1);
  }
}
int main()
{
  ios::sync_with_stdio(false);
  cin>>n>>m;
  rep(i,1,n-1)
  {
    int x,y;
    cin>>x>>y;
    arr(x,y); arr(y,x);
  }
  dfs(1,0);
  rep(i,1,19)
    rep(j,1,n)
      bz[j][i]=bz[bz[j][i-1]][i-1];
  rep(i,1,m)
  {
    int x,y;
    cin>>x>>y;
    int k=lca(x,y);
    ve[k].push_back(x); ve[k].push_back(y);
    ve3[x].push_back(k); ve3[y].push_back(k);
  }
  int q;
  cin>>q;
  rep(i,1,q)
  {
    int x,t;
    cin>>x>>t;
    ve2[x].push_back((re){i,t});
  }
  dfs2(1,0);
  rep(i,1,q) cout<<max(0,ans[i])<<endl;
  return 0;
}

 

posted @ 2018-09-09 19:59  尹吴潇  阅读(173)  评论(0编辑  收藏  举报