• AGC015做题记录


    C

    树的性质是点-边=1

    森林联通块计数都可以这么做所以直接维护前缀和再把边界处理一下就好了

    //Love and Freedom.
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<cstdio>
    #define inf 20021225
    #define ll long long
    #define N 2100
    using namespace std;
    int read()
    {
        int f=1,s=0; char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9')    s=s*10+ch-'0',ch=getchar();
        return f*s;
    }
    int a[N][N],p[N][N],e[N][N],hp[N][N],lp[N][N],n,m; char ch[N];
    int main()
    {
        n=read(),m=read(); int Q=read();
        for(int i=1;i<=n;i++)
        {
            scanf("%s",ch+1);
            for(int j=1;j<=m;j++)
            {
                a[i][j]=ch[j]-'0';
                p[i][j]=p[i-1][j]+p[i][j-1]-p[i-1][j-1]+a[i][j];
                e[i][j]=e[i-1][j]+e[i][j-1]-e[i-1][j-1]+(a[i][j]&a[i-1][j])+(a[i][j-1]&a[i][j]);
                hp[i][j]=hp[i][j-1]+(a[i][j]&a[i-1][j]);
                lp[i][j]=lp[i-1][j]+(a[i][j]&a[i][j-1]);
            }
        }
        while(Q--)
        {
            int h1=read(),l1=read(),h2=read(),l2=read();
            int poi=p[h2][l2]-p[h2][l1-1]-p[h1-1][l2]+p[h1-1][l1-1];
            //printf("%d %d %d %d
    ",p[h2][l2],p[h2][l1-1],p[h1-1][l2],p[h1-1][l1-1]);
            int ed=e[h2][l2]-e[h2][l1-1]-e[h1-1][l2]+e[h1-1][l1-1];
            //printf("%d ",ed);
            ed -= hp[h1][l2]-hp[h1][l1-1];
            ed -= lp[h2][l1]-lp[h1-1][l1];
            //printf("%d %d %d %d
    ",hp[h1][l2],hp[h1][l1-1],lp[h2][l1],lp[h1-1][l1]);
            printf("%d
    ",poi-ed);
        }
        return 0;
    }
    C

    D

    神仙思路题(我没脑子)

    考虑首先AB的最长公共前缀一定可以丢掉

    然后下一位B是1A是0

    我么设这一位为p

    考虑[A,1<<p)的答案和[1<<p,B]的答案

    显然只取前面一个集合的答案就是(1<<p)-A

    只取后面的 我们考虑B接下来最高位的一个1 记为k

    那么答案就是[1<<p,(1<<p) + (1<<k+1)  -1]

    最后考虑两个都取 答案是[(1<<p)+A,(2<<p)-1]

    发现后面两个需要取并

    这类题的思路主要在于取值是区间因此答案也是区间

    //Love and Freedom.
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<cstdio>
    #define inf 20021225
    #define ll long long
    using namespace std;
    int read()
    {
        int f=1,s=0; char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9')    s=s*10+ch-'0',ch=getchar();
        return f*s;
    }
    int main()
    {
        ll a,b; scanf("%lld%lld",&a,&b); ll ans=0;
        if(a==b)    return puts("1"),0;
        for(int i=60;~i;i--)
            if((a>>i&1)!=(b>>i&1))
            {
                a&=(1ll<<i+1)-1; b&=(1ll<<i)-1;
                ll p=1ll<<i; ans+=p-a;
                for(;~i;i--)    if(b>>i&1)    break;
                i++; ans+=1ll<<i; a=max(1ll<<i,a);
                //printf("%lld %lld %lld
    ",ans,i,a);
                ans+=p-a;
                break;
            }
        printf("%lld
    ",ans);
        return 0;
    }
    D

    E

    其实就差一步了(枯了

    考虑一个点能染的点

    有显然的两种

    1.xj<xi vj>vj

    2.xj>xi vj<vi

    我们继续考虑一些复杂的

    发现对于位置位于当前点之前的速度最大的点若比它的速度大的话就一定会把所有速度小于这个最大值的所有点染色(想想为什么?)

    后面的同理

    所以按照速度排序以后变成了区间覆盖的方案数

    显然可以线段树优化(哦其实可以直接前缀和优化 可惜我懒qwq)

    所以就做完了

    //Love and Freedom.
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<cstdio>
    #define inf 20021225
    #define ll long long
    #define N 200100
    #define mdn 1000000007
    #define ls (x<<1)
    #define rs (x<<1|1)
    #define mid (l+r>>1)
    using namespace std;
    int read()
    {
        int f=1,s=0; char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9')    s=s*10+ch-'0',ch=getchar();
        return f*s;
    }
    void upd(int &x,int y){x+=x+y>=mdn?y-mdn:y;}
    int t[N<<2];
    void pushup(int x){t[x]=(t[ls]+t[rs])%mdn;}
    void modify(int x,int l,int r,int d,int val)
    {
        if(l==r){upd(t[x],val); return;}
        if(d<=mid)    modify(ls,l,mid,d,val);
        else    modify(rs,mid+1,r,d,val);
        pushup(x);
    }
    int query(int x,int l,int r,int LL,int RR)
    {
        if(LL<=l&&RR>=r)    return t[x]; int ans=0;
        if(LL<=mid)    upd(ans,query(ls,l,mid,LL,RR));
        if(RR>mid)    upd(ans,query(rs,mid+1,r,LL,RR));
        return ans;
    }
    struct node{int x,v,idx,idv;}a[N];
    struct seg{int l,r;}s[N];
    bool operator<(seg a,seg b){return a.r<b.r||(a.r==b.r&&a.l<b.l);}
    bool cmpv(node x,node y){return x.v<y.v;}
    bool cmpx(node x,node y){return x.x<y.x;}
    int pre[N],suf[N],n,v[N];
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++)    a[i].x=read(),a[i].v=read();
        sort(a+1,a+n+1,cmpv);
        for(int i=1;i<=n;i++)    a[i].idv=i,v[i]=a[i].v;
        sort(a+1,a+n+1,cmpx); //suf[n+1]=inf*99;
        for(int i=1;i<=n;i++)
        {
            if(i==1)    pre[1]=a[1].idv;
            else
            {
                if(a[i].v>v[pre[i-1]])    pre[i]=a[i].idv;
                else    pre[i]=pre[i-1];
            }
            a[i].idx=i;
        }
        for(int i=n;i;i--)
        {
            if(i==n)    suf[n]=a[n].idv;
            else
            {
                if(a[i].v<v[suf[i+1]])    suf[i]=a[i].idv;
                else    suf[i]=suf[i+1];
            }
        }
        modify(1,0,n,0,1);
        for(int i=1;i<=n;i++)
        {
            int r=pre[a[i].idx],l=suf[a[i].idx];
            s[i].l=l; s[i].r=r;
        }
        sort(s+1,s+n+1);
        for(int i=1;i<=n;i++)
        {
            int l=s[i].l,r=s[i].r;
            int val=query(1,0,n,l-1,r);
            modify(1,0,n,r,val);
        }
        printf("%d
    ",query(1,0,n,n,n));
        return 0;
    }
    E

    F

    第一问显然是Fib(昨天刚好学类欧于是反应贼快)

    第二问还8会 等我咕会

    我去世了 下一周 我们就考到了这个题/px

    具体做法很神仙 我懒得写了 大概就是考虑递推出来的组数都不会特别多

    然后考虑再从上一层推出当前答案即可

    //Love and Freedom.
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<cstdio>
    #include<vector>
    #define inf 20021225
    #define ll long long
    #define pa pair<ll,ll>
    #define mp make_pair
    #define pb push_back
    #define mdn 1000000007
    using namespace std;
    int read()
    {
        int f=1,s=0; char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9')    s=s*10+ch-'0',ch=getchar();
        return f*s;
    }
    ll fib[100]; vector<pa> ans[100];
    int work(ll a,ll b,ll x,ll y)
    {
        int cur=0;
        if(x>=b&&y>=a+b)    (cur+=(y-a)/b%mdn)%mdn;
        if(y>=b&&x>=a+b)    (cur+=(x-a)/b%mdn)%mdn;
        return cur;
    }
    int main()
    {
        int top; fib[0]=fib[top=1]=1;
        while(fib[top]<=4e18)    ++top,fib[top]=fib[top-1]+fib[top-2];
        ans[0].pb(mp(0ll,1ll)),ans[0].pb(mp(0ll,2ll));
        for(int i=0;i+3<=top;i++)
        {
            for(int j=0;j<ans[i].size();j++)
            {
                ll x=ans[i][j].first,y=ans[i][j].second; x+=y;
                while(x<=fib[i+3]+fib[i])
                {
                    if(x>y)    ans[i+1].pb(mp(y,x));
                    x+=y;
                }
            }
        }
        int q=read();
        while(q--)
        {
            ll x,y; scanf("%lld%lld",&x,&y);
            if(x>y)    swap(x,y); int cur=1;
            while(fib[cur+2]<=y&&fib[cur+1]<=x)    cur++;
            printf("%d ",cur); int sum=0;
            if(cur==1){printf("%lld
    ",x%mdn*y%mdn); continue;}
            for(int i=0;i<ans[cur-1].size();i++)
                (sum+=work(ans[cur-1][i].first,ans[cur-1][i].second,x,y))%=mdn;
            printf("%d
    ",sum);
        }
        return 0;
    }
    F
  • 相关阅读:
    如何使用Orchard搭建敏捷个人的网站(1)
    英语:敏捷英语学习开始了
    英语:普特三步听写法(转载)
    色拉英语第一集第五幕:好胖的一只鸟
    介绍一个基于ASP.NET MVC的框架Catharsis
    色拉英语第2集第3幕:He’s my favorite
    Orchard:如何生成Hello World模块
    如何使用Orchard搭建敏捷个人的网站(2)
    色拉英语第一集第四幕:我不喜欢北京烤鸭
    色拉英语第一集第二幕:请问南京路怎么走?
  • 原文地址:https://www.cnblogs.com/hanyuweining/p/11980182.html
Copyright © 2020-2023  润新知