码迷,mamicode.com
首页 > 其他好文 > 详细

AGC015做题记录

时间:2019-12-03 23:54:45      阅读:183      评论:0      收藏:0      [点我收藏+]

标签:get   operator   区间   复杂   昨天   n+1   题记   ide   线段树   

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\n",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\n",hp[h1][l2],hp[h1][l1-1],lp[h2][l1],lp[h1-1][l1]);
        printf("%d\n",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\n",ans,i,a);
            ans+=p-a;
            break;
        }
    printf("%lld\n",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\n",query(1,0,n,n,n));
    return 0;
}
E

 

F

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

第二问还8会 等我咕会

AGC015做题记录

标签:get   operator   区间   复杂   昨天   n+1   题记   ide   线段树   

原文地址:https://www.cnblogs.com/hanyuweining/p/11980182.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!