2021年集训(8.2~8.4)

2021年集训(8.2~8.4)

这两天疫情突然来袭,烟台的形势突然紧张起来……
敌兵布阵
传送门

//https://vjudge.ppsucxtt.cn/contest/450704#problem/A
#include <stdio.h>
#include <string.h>
#define N 50005
int number[N],L[4*N],R[4*N],tree[4*N];
void Pushup(int id)
{
    tree[id]=tree[2*id]+tree[2*id+1];
}
void Build(int l,int r,int id)
{
    L[id]=l,R[id]=r;
    if(l==r)
    {
        tree[id]=number[l];
        return ;
    }
    int mid=(l+r)/2;
    Build(l,mid,2*id);
    Build(mid+1,r,2*id+1);
    Pushup(id);
}
void Update(int n,int m,int id)
{
    if(L[id]==n&&R[id]==n)
    {
        tree[id]+=m;
        return ;
    }
    int mid=(L[id]+R[id])/2;
    if(n<=mid)
        Update(n,m,2*id);
    else
        Update(n,m,2*id+1);
    Pushup(id);
}
int Query(int l,int r,int id)
{
    if(L[id]>=l&&R[id]<=r)
        return tree[id];
    int ans=0;
    int mid=(L[id]+R[id])/2;
    if(l<=mid)
        ans+=Query(l,r,2*id);
    if(r>mid)
        ans+=Query(l,r,2*id+1);
    return ans;
}
int main()
{
    int T;
    scanf("%d",&T);
    for(int i=1;i<=T;i++)
    {
        memset(L,0,sizeof(L));
        memset(R,0,sizeof(R));
        memset(tree,0,sizeof(tree));
        printf("Case %d:\n",i);
        int n;
        scanf("%d",&n);
        for(int j=1;j<=n;j++)
            scanf("%d",&number[j]);
        Build(1,n,1);
        char opt[10];
        while(scanf("%s",&opt)!=EOF)
        {
            if(strcmp(opt,"Add")==0)
            {
                int n,m;
                scanf("%d%d",&n,&m);
                Update(n,m,1);
            }
            if(strcmp(opt,"Sub")==0)
            {
                int n,m;
                scanf("%d%d",&n,&m);
                Update(n,-m,1);
            }
            if(strcmp(opt,"Query")==0)
            {
                int l,r;
                scanf("%d%d",&l,&r);
                printf("%d\n",Query(l,r,1));
            }
            if(strcmp(opt,"End")==0)
                break;
        }
    }
    return 0;
}

Lost Cows
传送门

//https://vjudge.ppsucxtt.cn/contest/450704#problem/B
#include <stdio.h>
#define N 8005
int number[N],ans[N],L[4*N],R[4*N],tree[4*N];
void Pushup(int id)
{
    tree[id]=tree[2*id]+tree[2*id+1];
}
void Build(int l,int r,int id)
{
    L[id]=l,R[id]=r;
    if(l==r)
    {
        tree[id]=1;
        return ;
    }
    int mid=(l+r)/2;
    Build(l,mid,2*id);
    Build(mid+1,r,2*id+1);
    Pushup(id);
}
int Query(int n,int id)
{
    tree[id]--;
    if(L[id]==R[id])
        return L[id];
    int ans;
    if(tree[2*id]>=n)
        ans=Query(n,2*id);
    else
        ans=Query(n-tree[2*id],2*id+1);
    return ans;
}
int main()
{
    int n;
    scanf("%d",&n);
    Build(1,n,1);
    for(int i=1;i<=n;i++)
    {
        if(i==1)
            number[i]=0;
        else
            scanf("%d",&number[i]);
    }
    for(int i=n;i>=1;i--)
        ans[i]=Query(number[i]+1,1);
    for(int i=1;i<=n;i++)
        printf("%d\n",ans[i]);
    return 0;
}

Mayor’s posters(离散化)
传送门

//https://vjudge.ppsucxtt.cn/contest/450704#problem/C
//https://blog.csdn.net/CUCUC1/article/details/107370653
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 10005
int ans;
int left[N],right[N],number[4*N],tree[16*N],flag[N];
//left和right存原始数据,开1倍
//number存left和right中的元素,还可能有不少增补元素,所以开4倍
//tree开number的4倍也就是16倍
//flag用于记录当前颜色是否已被计算,避免出现重复计算的情况,开1倍
void Update(int L,int R,int x,int l,int r,int id)
{
    if(l>=L&&r<=R)
    {
        tree[id]=x;
        return ;
    }
    if(tree[id]!=-1)//相当于Pushdown,只不过没有写成单独的函数
    {
        tree[2*id]=tree[id];
        tree[2*id+1]=tree[id];
        tree[id]=-1;
    }
    int mid=(l+r)/2;
    if(L<=mid)
        Update(L,R,x,l,mid,2*id);
    if(R>mid)
        Update(L,R,x,mid+1,r,2*id+1);
}
void Query(int L,int R,int l,int r,int id)
{
    if(l>=L&&r<=R&&tree[id]!=-1)
    {
        if(!flag[tree[id]])
        {
            ans++;
            flag[tree[id]]=1;
        }
        return ;
    }
    if(l==r)
        return ;
    int mid=(l+r)/2;
    if(L<=mid)
        Query(L,R,l,mid,2*id);
    if(R>mid)
        Query(L,R,mid+1,r,2*id+1);
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        memset(left,0,sizeof(left));
        memset(right,0,sizeof(right));
        memset(number,0,sizeof(number));
        memset(tree,-1,sizeof(tree));
        memset(flag,0,sizeof(flag));
        int n,num=1;//num为number数组中元素的实际个数加1
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&left[i],&right[i]);
            number[num++]=left[i];
            number[num++]=right[i];
        }
        sort(number+1,number+num);//去重前排序
        num=unique(number+1,number+num)-number;//去重,最后减去的是number而不是number+1,保证了num为实际个数加1
        int cnt=num;//cnt用于循环计数
        for(int i=2;i<cnt;i++)//cnt本来就是实际个数加1,不用跑到第cnt次,只用跑到第cnt-1次
            if(number[i]>number[i-1]+1)
                number[num++]=number[i-1]+1;//如果相邻两元素相差大于1,则增补元素
        sort(number+1,number+num);//增补后排序
        for(int i=1;i<=n;i++)
        {
            int l=lower_bound(number+1,number+num,left[i])-number;//由于用的是lower_bound,所以最后只用减number就可以得到其在数组中的位置,而不用减number+1
            int r=lower_bound(number+1,number+num,right[i])-number;//由于用的是lower_bound,所以最后只用减number就可以得到其在数组中的位置,而不用减number+1
            Update(l,r,i,1,num-1,1);
        }
        ans=0;
        Query(1,num-1,1,num-1,1);
        printf("%d\n",ans);
    }
    return 0;
}

Just a Hook
传送门

//https://vjudge.ppsucxtt.cn/contest/450704#problem/D
#include <stdio.h>
#include <string.h>
#define N 100005
int L[4*N],R[4*N],tree[4*N],flag[4*N];
void Pushup(int id)
{
    tree[id]=tree[2*id]+tree[2*id+1];
}
void Build(int l,int r,int id)
{
    L[id]=l,R[id]=r;
    if(l==r)
    {
        tree[id]=1;
        return ;
    }
    int mid=(l+r)/2;
    Build(l,mid,2*id);
    Build(mid+1,r,2*id+1);
    Pushup(id);
}
void Pushdown(int id,int len)
{
    tree[2*id]=flag[id]*(len-len/2);
    tree[2*id+1]=flag[id]*(len/2);
    flag[2*id]=flag[id];
    flag[2*id+1]=flag[id];
    flag[id]=0;
}
void Update(int l,int r,int x,int id)
{
    if(L[id]>=l&&R[id]<=r)
    {
        tree[id]=x*(R[id]-L[id]+1);
        flag[id]=x;
        return ;
    }
    if(flag[id])
        Pushdown(id,R[id]-L[id]+1);
    int mid=(L[id]+R[id])/2;
    if(l<=mid)
        Update(l,r,x,2*id);
    if(r>mid)
        Update(l,r,x,2*id+1);
    Pushup(id);
}
int Query(int l,int r,int id)
{
    if(L[id]>=l&&R[id]<=r)
        return tree[id];
    if(flag[id])
        Pushdown(id,R[id]-L[id]+1);
    int ans=0;
    int mid=(L[id]+R[id])/2;
    if(l<=mid)
        ans+=Query(l,r,2*id);
    if(r>mid)
        ans+=Query(l,r,2*id+1);
    return ans;
}
int main()
{
    int T;
    scanf("%d",&T);
    for(int i=1;i<=T;i++)
    {
        memset(L,0,sizeof(L));
        memset(R,0,sizeof(R));
        memset(tree,0,sizeof(tree));
        memset(flag,0,sizeof(flag));
        int n;
        scanf("%d",&n);
        Build(1,n,1);
        int m;
        scanf("%d",&m);
        while(m--)
        {
            int l,r,x;
            scanf("%d%d%d",&l,&r,&x);
            Update(l,r,x,1);
        }
        printf("Case %d: The total value of the hook is %d.\n",i,Query(1,n,1));
    }
    return 0;
}

I Hate It
传送门

//https://vjudge.ppsucxtt.cn/contest/450704#problem/E
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 200005
int number[N],L[4*N],R[4*N],tree[4*N];
void Pushup(int id)
{
    tree[id]=max(tree[2*id],tree[2*id+1]);
}
void Build(int l,int r,int id)
{
    L[id]=l,R[id]=r;
    if(l==r)
    {
        tree[id]=number[l];
        return ;
    }
    int mid=(l+r)/2;
    Build(l,mid,2*id);
    Build(mid+1,r,2*id+1);
    Pushup(id);
}
void Update(int x,int y,int id)
{
    if(L[id]==x&&R[id]==x)
    {
        tree[id]=y;
        return ;
    }
    int mid=(L[id]+R[id])/2;
    if(x<=mid)
        Update(x,y,2*id);
    else
        Update(x,y,2*id+1);
    Pushup(id);
}
int Query(int l,int r,int id)
{
    if(L[id]>=l&&R[id]<=r)
        return tree[id];
    int ans1=0x80000000,ans2=0x80000000;
    int mid=(L[id]+R[id])/2;
    if(l<=mid)
        ans1=Query(l,r,2*id);
    if(r>mid)
        ans2=Query(l,r,2*id+1);
    return max(ans1,ans2);
}
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(L,0,sizeof(L));
        memset(R,0,sizeof(R));
        memset(tree,0,sizeof(tree));
        for(int i=1;i<=n;i++)
            scanf("%d",&number[i]);
        Build(1,n,1);
        while(m--)
        {
            char opt;
            getchar();
            scanf("%c",&opt);
            if(opt=='U')
            {
                int x,y;
                scanf("%d%d",&x,&y);
                Update(x,y,1);
            }
            if(opt=='Q')
            {
                int l,r;
                scanf("%d%d",&l,&r);
                printf("%d\n",Query(l,r,1));
            }
        }
    }
    return 0;
}

Ultra-QuickSort
传送门

//https://vjudge.ppsucxtt.cn/contest/450704#problem/F
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 500005
int L[4*N],R[4*N],tree[4*N];
struct node
{
    int n;
    int id;
}number[N];
bool cmp(node x,node y)
{
    if(x.n!=y.n)
        return x.n<y.n;
    else
        return x.id<y.id;
}
void Pushup(int id)
{
    tree[id]=tree[2*id]+tree[2*id+1];
}
void Build(int l,int r,int id)
{
    L[id]=l,R[id]=r;
    if(l==r)
        return ;
    int mid=(l+r)/2;
    Build(l,mid,2*id);
    Build(mid+1,r,2*id+1);
}
void Update(int n,int id)
{
    if(L[id]==R[id])
    {
        tree[id]++;
        return ;
    }
    int mid=(L[id]+R[id])/2;
    if(n<=mid)
        Update(n,2*id);
    else
        Update(n,2*id+1);
    Pushup(id);
}
int Query(int l,int r,int id)
{
    if(L[id]>=l&&R[id]<=r)
        return tree[id];
    int ans=0;
    int mid=(L[id]+R[id])/2;
    if(l<=mid)
        ans+=Query(l,r,2*id);
    if(r>mid)
        ans+=Query(l,r,2*id+1);
    return ans;
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF&&n)
    {
        memset(L,0,sizeof(L));
        memset(R,0,sizeof(R));
        memset(tree,0,sizeof(tree));
        Build(1,n,1);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&number[i].n);
            number[i].id=i;
        }
        sort(number+1,number+1+n,cmp);
        long long ans=0;
        for(int i=1;i<=n;i++)
        {
            ans+=Query(number[i].id+1,n,1);//???
            Update(number[i].id,1);//???
        }
        printf("%lld\n",ans);
    }
    return 0;
}

Buy Tickets
传送门

//https://vjudge.ppsucxtt.cn/contest/450704#problem/G
#include <stdio.h>
#include <string.h>
#define N 200005
int cnt;
int pos[N],val[N],ans[N],L[4*N],R[4*N],tree[4*N],number[4*N];
void Pushup(int id)
{
    tree[id]=tree[2*id]+tree[2*id+1];
}
void Build(int l,int r,int id)
{
    L[id]=l,R[id]=r;
    if(l==r)
    {
        tree[id]=1;
        return ;
    }
    int mid=(l+r)/2;
    Build(l,mid,2*id);
    Build(mid+1,r,2*id+1);
    Pushup(id);
}
void Update(int pos,int val,int id)
{
    tree[id]--;
    if(L[id]==R[id])
    {
        number[id]=val;
        return ;
    }
    if(tree[2*id]>=pos)
        Update(pos,val,2*id);
    else
        Update(pos-tree[2*id],val,2*id+1);
}
void output(int id)
{
    if(L[id]==R[id])
    {
        ans[cnt++]=number[id];
        return ;
    }
    output(2*id);
    output(2*id+1);
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        memset(L,0,sizeof(L));
        memset(R,0,sizeof(R));
        memset(tree,0,sizeof(tree));
        memset(number,0,sizeof(number));
        Build(1,n,1);
        for(int i=1;i<=n;i++)
            scanf("%d%d",&pos[i],&val[i]);
        for(int i=n;i>=1;i--)
            Update(pos[i]+1,val[i],1);
        cnt=1;
        output(1);
        for(int i=1;i<=n;i++)
        {
            if(i!=n)
                printf("%d ",ans[i]);
            else
                printf("%d\n",ans[i]);
        }
    }
    return 0;
}

Stars(树状数组)
传送门

//https://vjudge.ppsucxtt.cn/contest/450704#problem/H
#include <stdio.h>
#define N 32005
int tree[N],ans[N];
int lowbit(int x)
{
    return x&-x;
}
void Update(int id)
{
    for(int i=id;i<=N;i+=lowbit(i))
        tree[i]++;
}
int Query(int id)
{
    int sum=0;
    for(int i=id;i;i-=lowbit(i))
        sum+=tree[i];
    return sum;
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        ans[Query(++x)]++;
        Update(x);
    }
    for(int i=0;i<n;i++)
        printf("%d\n",ans[i]);
    return 0;
}

A Simple Problem with Integers
传送门

//https://vjudge.ppsucxtt.cn/contest/450704#problem/I
#include <stdio.h>
#define N 100005
int number[N],L[4*N],R[4*N],add[4*N];
long long tree[4*N];
void Pushup(int id)
{
    tree[id]=tree[2*id]+tree[2*id+1];
}
void Build(int l,int r,int id)
{
    L[id]=l,R[id]=r;
    if(l==r)
    {
        tree[id]=(long long)number[l];
        return ;
    }
    int mid=(l+r)/2;
    Build(l,mid,2*id);
    Build(mid+1,r,2*id+1);
    Pushup(id);
}
void Pushdown(int id,int len)
{
    tree[2*id]+=(long long)add[id]*(len-len/2);
    tree[2*id+1]+=(long long)add[id]*(len/2);
    add[2*id]+=add[id];
    add[2*id+1]+=add[id];
    add[id]=0;
}
void Update(int l,int r,int x,int id)
{
    if(L[id]>=l&&R[id]<=r)
    {
        add[id]+=x;
        tree[id]+=(long long)x*(R[id]-L[id]+1);
        return ;
    }
    if(add[id])
        Pushdown(id,R[id]-L[id]+1);
    int mid=(L[id]+R[id])/2;
    if(l<=mid)
        Update(l,r,x,2*id);
    if(r>mid)
        Update(l,r,x,2*id+1);
    Pushup(id);
}
long long Query(int l,int r,int id)
{
    if(L[id]>=l&&R[id]<=r)
        return tree[id];
    if(add[id])
        Pushdown(id,R[id]-L[id]+1);
    long long ans=0;
    int mid=(L[id]+R[id])/2;
    if(l<=mid)
        ans+=Query(l,r,2*id);
    if(r>mid)
        ans+=Query(l,r,2*id+1);
    return ans;
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&number[i]);
    Build(1,n,1);
    while(m--)
    {
        char opt;
        getchar();
        scanf("%c",&opt);
        if(opt=='C')
        {
            int l,r,x;
            scanf("%d%d%d",&l,&r,&x);
            Update(l,r,x,1);
        }
        if(opt=='Q')
        {
            int l,r;
            scanf("%d%d",&l,&r);
            printf("%lld\n",Query(l,r,1));
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值