AGC015做题记录

Posted hanyuweining

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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会 等我咕会

以上是关于AGC015做题记录的主要内容,如果未能解决你的问题,请参考以下文章

agc015E Mr.Aoki Incubator

AGC 015 E - Mr.Aoki Incubator

agc015D A or...or B Problem

AGC005做题小记

AGC006做题小记

做题agc006C - Rabbit Exercise——模型转换