【国庆集训】10.8

这次比赛不是很难(但是我也只有140),但竟然是第三名(捂脸)

T1:

clique
【题目描述】
数轴上有 n 个点,第 i 个点的坐标为 xi,权值为 wi。两个点 i,j
间存在一条边当且仅当 abs(xi-xj)>=wi+wj
你需要求出这张图的最大团的点数。(团就是两两之间有边的顶点
集合)
【输入数据】
第一行一个整数 n,接下来 n 行每行两个整数 xi,wi
【输出数据】
一行一个整数表示答案。
【样例输入】
4
2 3
3 1
6 1
0 2
【样例输出】
3
【数据范围】
对于 20%的数据, n<=10
对于 60%的数据, n<=1000
对于 100%的数据, n<=2000000<=|xi|,wi<=10^9

考场上看了几眼就去做T2,结果发现T2不会,打了暴力又回来

画图手玩样例,就像到正解了。。。。。。

不就是一个选最多不重合区间吗

但是后来某巨佬讲课才知道用最长上升子序列+线段树优化

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define cg ch=getchar()

const int _=500002;
ll number,x[_],w[_],f[_],tl,ans=1;
struct node{ll l,r;}room[_];

ll read(){
    ll s=0,w=1;char cg;
    while(ch<'0'||ch>'9')w=(ch=='-')?-1:1,cg;
    while(ch>='0'&&ch<='9')s=s*10+ch-'0',cg;
    return s*w;
}

bool cmp(node a,node b){
    if(a.r!=b.r)return a.r<b.r;
    return a.l<b.l;
}

int main(){
    freopen("clique.in","r",stdin);
    freopen("clique.out","w",stdout);
    number=read();
    for(int i=1;i<=number;i++)x[i]=read(),w[i]=read(),room[i].l=x[i]-w[i],room[i].r=x[i]+w[i];
    sort(room+1,room+number+1,cmp);
    f[1]=1;tl=room[1].r;
    for(int i=2;i<=number;i++){
        f[i]=f[i-1];
        if(room[i].l>=tl){
            f[i]=f[i-1]+1;tl=room[i].r;
        }
    }
    cout<<f[number];
    return 0;
}

T2:

mod
【题目描述】
给定一个长度为 n 的非负整数序列 a,你需要支持以下操作:
1:给定 l,r,输出 a[l]+a[l+1]+…+a[r]
2:给定 l,r,x,将 a[l],a[l+1],…,a[r]x 取模。
3:给定 k,y,将 a[k]修改为 y
【输入数据】
第一行两个整数 n,m。第二行 n 个整数 a[1]~a[n]。接下来 m 行每
3 4 个整数表示操作。
【输出数据】
对于每个操作 1,输出一行一个整数表示答案。
【样例输入】
5 5
1 2 3 4 5
2 3 5 4
3 3 5
1 2 5
2 1 3 3
1 1 3
【样例输出】
8 5
【数据范围】
对于 40%的数据, n,m<=1000
对于 100%的数据,n,m<=1000001<=l<=r<=n1<=k<=n1<=x<=10^9
0<=a[i],y<=10^9

看到题目时,我的心中毫无波澜,想着一个简简单单的板子题,不就是送分的吗

结果发现要%。。。。。。

做完T1再来想,发现用线段树维护区间和和区间最大值,取膜直接暴力

但是当区间最大值 < 当前需要%的,就可以退出(这应该是个小小的优化)

可是我写挂了。。。。。。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define cg ch=getchar()

const int _=100002;
ll number,magic,ans;
struct node{ll l,r,w,maxx;}tree[_*4+1];

ll read(){
    ll s=0,w=1;char cg;
    while(ch<'0'||ch>'9')w=(ch=='-')?-1:1,cg;
    while(ch>='0'&&ch<='9')s=s*10+ch-'0',cg;
    return s*w;
}

void Build(ll k,ll l,ll r){
    tree[k].l=l;tree[k].r=r;
    if(l==r){
        tree[k].w=tree[k].maxx=read();
        return;
    }
    ll mid=(tree[k].l+tree[k].r)>>1;
    Build(k*2,l,mid);Build(k*2+1,mid+1,r);
    tree[k].w=tree[k*2].w+tree[k*2+1].w;
    tree[k].maxx=max(tree[k*2].maxx,tree[k*2+1].maxx);
}

void getsum(ll k,ll l,ll r){
    if(l<=tree[k].l&&tree[k].r<=r){
        ans+=tree[k].w;return;
    }
    ll mid=(tree[k].l+tree[k].r)>>1;
    if(l<=mid)getsum(k*2,l,r);
    if(r>mid)getsum(k*2+1,l,r);
}

void change1(ll k,ll l,ll r,ll x){
    if(tree[k].maxx<x)return;
    if(tree[k].l==tree[k].r){
        tree[k].w%=x;tree[k].maxx%=x;
        return;
    }
    ll mid=(tree[k].l+tree[k].r)>>1;
    if(l<=mid)change1(k*2,l,r,x);
    if(mid<r)change1(k*2+1,l,r,x);
    tree[k].w=tree[k*2].w+tree[k*2+1].w;
    tree[k].maxx=max(tree[k*2].maxx,tree[k*2+1].maxx);
}

void change2(ll k,ll x,ll y){
    if(tree[k].l==tree[k].r){
        tree[k].w=tree[k].maxx=y;return;
    }
    ll mid=(tree[k].l+tree[k].r)>>1;
    if(x<=mid)change2(k*2,x,y);
    else change2(k*2+1,x,y);
    tree[k].w=tree[k*2].w+tree[k*2+1].w;
    tree[k].maxx=max(tree[k*2].maxx,tree[k*2+1].maxx);
}

int main(){
    freopen("mod.in","r",stdin);
    freopen("mod.out","w",stdout);
    number=read();magic=read();
    Build(1,1,number);
    for(int i=1;i<=magic;i++){
        ans=0;
        ll pd=read(),l=read(),r=read(),x;
        if(pd==1){
            getsum(1,l,r);cout<<ans<<endl;
        }
        if(pd==2)x=read(),change1(1,l,r,x);
        if(pd==3)change2(1,l,r);
    }
    return 0;
}

T3:没学过,忽略

猜你喜欢

转载自www.cnblogs.com/GMSD/p/11639654.html
今日推荐