20190818考试反思

  题不难,可我答的不够好。

  T1时间太长,忘了公式又推了半天。边码对拍边试公式,大概开考40分钟才A掉。

  T2想的太少,还是思路差一点拔高,大众分都能想到,应该能顺着想出来线段树思路。

  T3。。。。。因为给的时间过少,set建边不会,摸索半天,大概30分钟才把边建出来,然后打的时候发现我的dfs思路死了就剩10min了,立马想到他tarjan+topu,然后10分钟码完了撞了一个变量名,爆0了。

  这次考试大概比较简单,但是问题有

1.线段树的运用不够灵活,一般是能够化出来一个式子,把和变量有关的放到一块,扔到树上,然后用常量进行判断修改查询等。

2.T3有向图无向图搞混,这是不应该的,在确定要用图论来做的时候,先判断用哪部分知识。

  T1:裸catalan,没了。

#include<iostream>
#include<cstdio>
using namespace std;
const int N=2000020,mod=20100403;
int fac[N],inv[N];
inline int rd()
{
    int s=0,w=1;
    char cc=getchar();
    for(;cc<'0'||cc>'9';cc=getchar()) if(cc=='-') w=-1;
    for(;cc>='0'&&cc<='9';cc=getchar()) s=(s<<3)+(s<<1)+cc-'0';
    return s*w;
}
int qpow(int a,int k)
{
    int ans=1;
    for(;k;k>>=1,a=1ll*a*a%mod) if(k&1) ans=1ll*ans*a%mod;
    return ans;
}
int C(int n,int m)
{
    if(n<m) return 0;
    return 1ll*fac[n]*inv[n-m]%mod*inv[m]%mod;
}
int main()
{
    //freopen("data.in","r",stdin);
    //freopen("data.out","w",stdout);
    int n=rd(),m=rd();fac[0]=1;
    if(n<m) return puts("0"),0;
    for(int i=1;i<=n+m;i++) fac[i]=1ll*fac[i-1]*i%mod;
    inv[n+m]=qpow(fac[n+m],mod-2);
    for(int i=n+m;i>=1;i--) inv[i-1]=1ll*inv[i]*i%mod;
    printf("%d\n",(C(n+m,n)-C(n+m,m-1)+mod)%mod);
}
/*
g++ 1.cpp -o 1
./1
4 3
*/
View Code

  T2:线段树思路很顺利,不知为什么他们都沉迷于排序二分。暴力$O(nm)$很好打,考虑要优化哪部分,因为$O(m)$的部分每次都不一样,所以不优化它,考虑优化每一轮的计算,我们要的是一段能喝的权值和,只要排除不能喝的贡献即可,咋就不能喝了,$c[i]<ans+i$就不行了,就是当前的答案和这一轮他之前和他自己的消耗的次数,变量放一边$c[i]-i>=ans$为合法,只要区间最小值,然后如果都合法,那么直接加整个区间的贡献,否则对点挨个删,删到合法后加贡献,注意删完一个区间后边的排序就少一$c[i]-i$应该加一,然后就没了。每个点最多删一次,复杂度$O(nlogn)$

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=100020;
long long inf=0x7ffffffffffffff;
long long f[N],a[N],c[N],w[N];
struct tree{long long w,c,f,p;}tr[N*4];
inline long long rd()
{
    long long s=0,w=1;
    register char cc=getchar();
    for(;cc<'0'||cc>'9';cc=getchar()) if(cc=='-') w=-1;
    for(;cc>='0'&&cc<='9';cc=getchar()) s=(s<<3)+(s<<1)+cc-'0';
    return s*w;
}
inline void updata(int k)
{
    tr[k].w=tr[k<<1].w+tr[k<<1|1].w;
    tr[k].c=min(tr[k<<1].c,tr[k<<1|1].c);
    if(tr[k<<1].c<=tr[k<<1|1].c) tr[k].p=tr[k<<1].p;
    else tr[k].p=tr[k<<1|1].p;
}
inline void modify(int k,int l,int r,int w){tr[k].c+=w;tr[k].f+=w;}
inline void down(int k,int l,int r)
{
    int mid=l+r>>1;
    modify(k<<1,l,mid,tr[k].f);
    modify(k<<1|1,mid+1,r,tr[k].f);
    tr[k].f=0;
}
void build(int k,int l,int r)
{
    if(l==r)
    {
        tr[k].c=c[l]-l;
        tr[k].w=1;
        tr[k].p=l;
        return;
    }
    int mid=l+r>>1;
    build(k<<1,l,mid);build(k<<1|1,mid+1,r);
    updata(k);
}
void cut(int k,int l,int r,int id)
{
    if(l==r){tr[k].w=0,tr[k].c=inf;return;}
    int mid=l+r>>1;
    if(tr[k].f)down(k,l,r);
    if(id<=mid) cut(k<<1,l,mid,id);
    else cut(k<<1|1,mid+1,r,id);
    updata(k);
}
void add(int k,int l,int r,int x,int y,int w)
{
    if(l==x&&r==y){modify(k,l,r,w);return;}
    int mid=l+r>>1;
    if(tr[k].f) down(k,l,r);
    if(y<=mid) add(k<<1,l,mid,x,y,w);
    else if(x>mid) add(k<<1|1,mid+1,r,x,y,w);
    else add(k<<1,l,mid,x,mid,w),add(k<<1|1,mid+1,r,mid+1,y,w);
    updata(k);
}
int main()
{
    int n=rd(),m=rd();
    long long x=rd();
    for(int i=1;i<=n;i++) w[i]=rd();
    for(int i=1;i<=n;i++) a[i]=rd();
    for(int i=1;i<=n;i++)
    {
        c[i]=(x-w[i])/a[i]+1;
        if(c[i]<0) c[i]=0;
    }
    build(1,1,n);
    long long ans=0;
    while(m--)
    {
        while(tr[1].c<ans)
        {
            int t=tr[1].p;
            cut(1,1,n,t);
            add(1,1,n,t,n,1);
        }
        ans+=tr[1].w;
    }
    printf("%lld\n",ans);
}
/*
g++ -std=c++11 2.cpp -o 2
./2
5 2 20
15 14 13 12 12
1 1 1 1 1
*/
View Code

 

  T3:sb题,正解$O(n^{2})$,我服了,最终还是看出来topu了,也打出来了,但是太紧张导致撞变量了。

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=100020;
long long inf=0x7ffffffffffffff;
long long f[N],a[N],c[N],w[N];
struct tree{long long w,c,f,p;}tr[N*4];
inline long long rd()
{
    long long s=0,w=1;
    register char cc=getchar();
    for(;cc<'0'||cc>'9';cc=getchar()) if(cc=='-') w=-1;
    for(;cc>='0'&&cc<='9';cc=getchar()) s=(s<<3)+(s<<1)+cc-'0';
    return s*w;
}
inline void updata(int k)
{
    tr[k].w=tr[k<<1].w+tr[k<<1|1].w;
    tr[k].c=min(tr[k<<1].c,tr[k<<1|1].c);
    if(tr[k<<1].c<=tr[k<<1|1].c) tr[k].p=tr[k<<1].p;
    else tr[k].p=tr[k<<1|1].p;
}
inline void modify(int k,int l,int r,int w){tr[k].c+=w;tr[k].f+=w;}
inline void down(int k,int l,int r)
{
    int mid=l+r>>1;
    modify(k<<1,l,mid,tr[k].f);
    modify(k<<1|1,mid+1,r,tr[k].f);
    tr[k].f=0;
}
void build(int k,int l,int r)
{
    if(l==r)
    {
        tr[k].c=c[l]-l;
        tr[k].w=1;
        tr[k].p=l;
        return;
    }
    int mid=l+r>>1;
    build(k<<1,l,mid);build(k<<1|1,mid+1,r);
    updata(k);
}
void cut(int k,int l,int r,int id)
{
    if(l==r){tr[k].w=0,tr[k].c=inf;return;}
    int mid=l+r>>1;
    if(tr[k].f)down(k,l,r);
    if(id<=mid) cut(k<<1,l,mid,id);
    else cut(k<<1|1,mid+1,r,id);
    updata(k);
}
void add(int k,int l,int r,int x,int y,int w)
{
    if(l==x&&r==y){modify(k,l,r,w);return;}
    int mid=l+r>>1;
    if(tr[k].f) down(k,l,r);
    if(y<=mid) add(k<<1,l,mid,x,y,w);
    else if(x>mid) add(k<<1|1,mid+1,r,x,y,w);
    else add(k<<1,l,mid,x,mid,w),add(k<<1|1,mid+1,r,mid+1,y,w);
    updata(k);
}
int main()
{
    int n=rd(),m=rd();
    long long x=rd();
    for(int i=1;i<=n;i++) w[i]=rd();
    for(int i=1;i<=n;i++) a[i]=rd();
    for(int i=1;i<=n;i++)
    {
        c[i]=(x-w[i])/a[i]+1;
        if(c[i]<0) c[i]=0;
    }
    build(1,1,n);
    long long ans=0;
    while(m--)
    {
        while(tr[1].c<ans)
        {
            int t=tr[1].p;
            cut(1,1,n,t);
            add(1,1,n,t,n,1);
        }
        ans+=tr[1].w;
    }
    printf("%lld\n",ans);
}
/*
g++ -std=c++11 2.cpp -o 2
./2
5 2 20
15 14 13 12 12
1 1 1 1 1
*/
View Code

 

 

posted @ 2019-08-19 06:33  starsing  阅读(159)  评论(1编辑  收藏  举报