2017.10.25 模拟赛

题目链接

T1

贪心或二分答案

#include <algorithm>
#include <cstring>
#include <cctype>
#include <cstdio>
#define N 100005

using namespace std;
int n;
struct node
{
    int Ti,Si;
    bool operator<(node a)const
    {
        return Si<a.Si;
    }
}Task[N];
int main()
{
    freopen("manage.in","r",stdin);
    freopen("manage.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d%d",&Task[i].Ti,&Task[i].Si);
    sort(Task+1,Task+n+1);
    bool flag=false;
    int tim=0,ans=0x3f3f3f3f;
    for(int i=1;i<=n;i++)
    {
        if(tim+Task[i].Ti>Task[i].Si)
        {
            flag=true;
            break;
        }
        tim+=Task[i].Ti;
        ans=min(ans,Task[i].Si-tim);
    }
    if(flag) puts("-1");
    else printf("%d\n",ans);
    fclose(stdin); fclose(stdout);
    return 0;
}
贪心
#include <algorithm>
#include <cstdio>

inline void read(int &x)
{
    x=0; register char ch=getchar();
    for(; ch>'9'||ch<'0'; ) ch=getchar();
    for(; ch>='0'&&ch<='9'; ch=getchar()) x=x*10+ch-'0';
}
const int N(100005);
struct Work {
    int t,s;
    bool operator < (const Work&x)const
    {
        if(s==x.s) return t<x.t;
        return s<x.s;
    }
}job[N];

int ans=-1,L,R,Mid,n;
inline bool check(int x)
{
    for(int i=1; i<=n; ++i)
    {
        if(x+job[i].t>job[i].s) return 0;
        x+=job[i].t;
    }
    return 1;
}

int Presist()
{
    freopen("manage.in","r",stdin);
    freopen("manage.out","w",stdout);
    
    read(n);
    for(int t,i=1; i<=n; ++i)
        read(job[i].t),read(job[i].s);
    std::sort(job+1,job+n+1);
    for(R=job[1].s-job[1].t+1; L<=R; )
    {
        Mid=L+R>>1;
        if(check(Mid))
        {
            ans=Mid;
            L=Mid+1;
        }
        else R=Mid-1;
    }
    printf("%d\n",ans);
    return 0;
}

int Aptal=Presist();
int main(int argc,char**argv){;}
二分

 

T2

sum[i]为前缀和,num[i]为i颜色的数量
那么i这种颜色对答案的贡献就是C(sum[i]-1,num[i]-1)%mod;
因为i的最后一个不能放到i+1最后一个的前面,所以要减一
分步乘法原理。

#include <cstdio>
#include <cctype>
#define Mod 998244353
#define N 1000070
typedef long long LL;
inline void read(LL &x)
{
    bool f=0;register char ch=getchar();
    for(x=0;!isdigit(ch);ch=getchar()) if(ch=='-') f=1;
    for(;isdigit(ch);x=x*10+ch-'0',ch=getchar());
    x=f?-x:x;
}
LL n,ans=1,num[N],sum[N],f[N],fac[N],inv[N];
void init()
{
    f[0]=inv[0]=fac[0]=f[1]=inv[1]=fac[1]=1;
    for(LL i=2;i<=N;++i)
    {
        fac[i]=(fac[i-1]%Mod*i%Mod)%Mod;
        f[i]=(Mod-Mod/i)*f[Mod%i]%Mod;
        inv[i]=(inv[i-1]%Mod*f[i]%Mod)%Mod;
    }
}
LL C(LL m,LL n)
{
    if(n>m) return 1;
    return fac[m]%Mod*inv[n]%Mod*inv[m-n]%Mod;
}
void print(LL ans)
{
    if(ans/10) print(ans/10);
    putchar(ans%10+'0');
}
int main(int argc,char *argv[])
{
    freopen("qiang.in","r",stdin);
    freopen("qiang.out","w",stdout);
    read(n);
    for(LL i=1;i<=n;++i) read(num[i]),sum[i]=sum[i-1]+num[i];
    init();
    for(LL i=2;i<=n;++i) ans=(ans%Mod*C(sum[i]-1,num[i]-1)%Mod)%Mod;
    print(ans);
    fclose(stdin); fclose(stdout);
    return 0;
}
std

 

T3

题目来源 codechef NOV14.FNCS Chef and Churu
80分 黔驴技穷了 比着std写的 std不知为何 0分啊我也很绝望。
对于每个fi,可以直接使用树状数组求出。
所以我们可以使用分块,中间的直接用块的答案,边上的用树状数组。
首先我们进行预处理,记录第i块中每个编号的个数,这里用前缀和,并求出每个块的和。
对于修改操作1 x y,我们要维护树状数组和块状数组。
树状数组:直接维护。
块状数组:找到每个块中x的个数,这块的sum加上x*(y-a[x])。
最后把a[x]赋成y。
对于查询操作2 x y。
中间的块我们直接用块状数组的答案,O(√n)。
边上的两块我们用树状数组暴力求所有的f[i],O(√n log n)。
所以总的时间复杂度为O(n √n log n)。

#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cctype>
#define N 100005

using namespace std;
typedef long long LL;
inline void read(LL &x)
{
    bool f=0;register char ch=getchar();
    for(x=0;!isdigit(ch);ch=getchar()) if(ch=='-') f=1;
    for(;isdigit(ch);x=x*10+ch-'0',ch=getchar());
    x=f?-x:x;
}
LL tag[N],val[N<<2|1];
int n,q,a[N],x[N],y[N],cnt[N<<2|1],mid[N<<2|1];
struct node
{
    int x,y,id;
    bool operator<(node a)const
    {
        if(x==a.x) return y<a.y;
        else return x<a.x;
    }
}b[N];
inline int lowbit(int &x) {return x&(-x);}
inline void add(int x,int y) {for(;x<=n;x+=lowbit(x)) tag[x]+=y;}
inline LL ask(int x)
{
    LL ret=0;
    for(;x;x-=lowbit(x)) ret+=tag[x];
    return ret;
}
void build(int k,int l,int r)
{
    if(l==r) {val[k]=ask(y[l])-ask(x[l]-1);return;}
    mid[k]=(l+r)>>1;
    build(k<<1,l,mid[k]);
    build(k<<1|1,mid[k]+1,r);
    val[k]=val[k<<1]+val[k<<1|1];
}
void modify(int k,int l,int r,int t)
{
    if(l==r) {val[k]=ask(y[l])-ask(x[l]-1);return;}
    if(t<=mid[k]) modify(k<<1,l,mid[k],t);
    else modify(k<<1|1,mid[k]+1,r,t);
    val[k]=val[k<<1]+val[k<<1|1];
}
LL query(int k,int l,int r,int x,int y)
{
    if(l>=x&&r<=y) return val[k];
    LL ret=0;
    if(x<=mid[k]) ret+=query(k<<1,l,mid[k],x,y);
    if(y>mid[k]) ret+=query(k<<1|1,mid[k]+1,r,x,y);
    return ret;
}
int main(int argc,char *argv[])
{
    freopen("sum.in","r",stdin);
    freopen("sum.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;++i) scanf("%d",&a[i]),add(i,a[i]);
    for(int i=1;i<=n;++i)
    {
        scanf("%d%d",&x[i],&y[i]);
        b[i].x=x[i];
        b[i].y=y[i];
        b[i].id=i;
    }
    build(1,1,n);
    sort(b+1,b+1+n);
    scanf("%d",&q);
    for(int opt,l,r;q--;)
    {
        scanf("%d%d%d",&opt,&l,&r);
        if(opt==1)
        {
            add(l,r-a[l]),a[l]=r;
            for(int i=1;i<=n;++i)
            {
                if(b[i].x<=l) modify(1,1,n,b[i].id);
                else break;
            }
        }
        else cout<<query(1,1,n,l,r)<<"\n";
    }
    fclose(stdin); fclose(stdout);
    return 0;
}
考场20分代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>

#define ll long long
#define N 100007
#define S 400

using namespace std;
int n,m,unit,num;
int fl[N],fr[N],a[N];
int cnt[S][N];
ll ta[N],sumb[S];

inline int read()
{
    int x=0,f=1;char c=getchar();
    while(c>‘9‘||c<‘0‘){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();}
    return x*f;
}

inline int lowbit(int x){return x&-x;}

inline void ins(int i,int add)
{
    for(;i<=n;i+=lowbit(i)) ta[i]+=add;
}

inline void update(int x,int y)
{
    ins(x,y-a[x]);
    for(int i=1;i<=num;i++) sumb[i]+=(ll)cnt[i][x]*(y-a[x]);
    a[x]=y;
}

inline ll getsum(int i)
{
    ll sum=0;
    for(;i;i-=lowbit(i)) sum+=ta[i];
    return sum;
}

ll query(int l,int r)
{
    int lblock=(l-1)/unit+1,rblock=(r-1)/unit+1;ll sum=0;
    if(lblock==rblock)
      for(int i=l;i<=r;i++)
        sum+=getsum(fr[i])-getsum(fl[i]-1);
    else
    {
        for(int i=lblock+1;i<=rblock-1;i++) sum+=sumb[i];
        for(int i=l;i<=lblock*unit;i++) sum+=getsum(fr[i])-getsum(fl[i]-1);
        for(int i=(rblock-1)*unit+1;i<=r;i++) sum+=getsum(fr[i])-getsum(fl[i]-1);
    }return sum;
}

int main()
{
    freopen("sum.in","r",stdin);
    freopen("sum.out","w",stdout);
    
    n=read();
    for(int i=1;i<=n;i++) a[i]=read();
    for(int i=1;i<=n;i++) fl[i]=read(),fr[i]=read();
    for(int i=1;i<=n;i++) ins(i,a[i]);
    
    int nowblock=0;
    unit=(int)sqrt(n),num=unit+(unit*unit!=n);
    for(int i=1;i<=n;i++)
    {
        if(i%unit==1) nowblock++;
        cnt[nowblock][fl[i]]++;
        cnt[nowblock][fr[i]+1]--;
    }
    for(int i=1;i<=num;i++)
      for(int j=1;j<=n;j++)
      {
            cnt[i][j]+=cnt[i][j-1];
            sumb[i]+=(ll) cnt[i][j]*a[j];
      }
      
    int k,x,y;
    m=read();
    for(int i=1;i<=m;i++)
    {
        k=read();x=read();y=read();
        if(k==1) update(x,y);
        else printf("%I64d\n",query(x,y));
    }
    fclose(stdin);fclose(stdout);
    return 0;
}
std

 

posted @ 2017-10-25 16:09  杀猪状元  阅读(180)  评论(0编辑  收藏  举报