9.20...

40+0+30=70 rank10 这都前十……
T1,考试时就想斜率dp了,结果推出来的式子没法搞,又推了一些没用的性质,最后放弃了打了40分暴力。正解根号算法,
转移时包含的颜色最多有 n 个,记录每个位置的上一个和下一个相同颜色的位置,转移时,pos[j]表示pos[j]+1~i中有不超过j种颜色,当i++时,要巧妙的转移(详见代码),总复杂度 O(nn)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#define N 40005
using namespace std;
int n,nn,m,c[N],nxt[N],pre[N],last[N],pos[N];
int cnt[N];
int f[N];
int main(){
    scanf("%d%d",&n,&m);
    nn=min((int)sqrt(n),m);
    for(int i=1;i<=n;i++){
        scanf("%d",&c[i]);
        pre[i]=last[c[i]];
        nxt[last[c[i]]]=i;
        last[c[i]]=i;
    }
    for(int i=1;i<=m;i++)nxt[last[i]]=n+1;
    for(int i=1;i<=n;i++){
        f[i]=f[i-1]+1;
        for(int j=1;j<=nn;j++){
            if(pre[i]<=pos[j]){
                cnt[j]++;
                if(cnt[j]>j){
                    while(nxt[pos[j]+1]<=i)pos[j]++;
                    pos[j]++;cnt[j]--;
                }
            }
            f[i]=min(f[i],f[pos[j]]+j*j);
        }
    }
    printf("%d\n",f[n]);
    return 0;
}

T2,考试时大部分时间在搞这个题,结果爆零了,蜜汁flag(打的时间和分数成反比),正解是搞一个覆盖所有的大矩形,肯定有某个小矩形是在它的某个角,暴力搜就行。。。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
int n, maxx,maxy,minx,miny,ANS;
struct data{
    int x,y,vis;
}d[20005];
int vis[20005];
bool flag;
void dfs(int step,int l,int wh){
    if(flag==1)return;
    if(step==4){
        for(int i=1;i<=n;i++)if(!vis[i])return;
        flag=1;return ;
    }
    maxx=maxy=-1000000001;
    minx=miny=1000000001;
    for(int i=1;i<=n;i++){
        if(!vis[i]||vis[i]>=step){
            vis[i]=0;
            maxx=max(maxx,d[i].x);maxy=max(maxy,d[i].y);
            minx=min(minx,d[i].x);miny=min(miny,d[i].y);
        }
    }
    if(wh==1){
        for(int i=1;i<=n;i++)if(!vis[i])
            if(d[i].x-minx<=l&&maxy-d[i].y<=l)vis[i]=step;
        for(int i=1;i<=4;i++)dfs(step+1,l,i);
    }
    else if(wh==2){
        for(int i=1;i<=n;i++)if(!vis[i])
            if(maxx-d[i].x<=l&&maxy-d[i].y<=l)vis[i]=step;
        for(int i=1;i<=4;i++)dfs(step+1,l,i);
    }
    else if(wh==3){
        for(int i=1;i<=n;i++)if(!vis[i])
            if(d[i].x-minx<=l&&d[i].y-miny<=l)vis[i]=step;
        for(int i=1;i<=4;i++)dfs(step+1,l,i);
    }
    else if(wh==4){
        for(int i=1;i<=n;i++)if(!vis[i])
            if(maxx-d[i].x<=l&&d[i].y-miny<=l)vis[i]=step;
        for(int i=1;i<=4;i++)dfs(step+1,l,i);
    }
}
bool check(int x){
    flag=0;
    for(int i=1;i<=4;i++){
        dfs(1,x,i);
        if(flag)return 1;
    }return 0;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%lld%lld",&d[i].x,&d[i].y);
        maxx=max(maxx,d[i].x);maxy=max(maxy,d[i].y);
        minx=min(minx,d[i].x);miny=min(miny,d[i].y);
    }
    int l=1,r=max(maxx-minx,maxy-miny),mid;
    while(l<=r){
        mid=(l+r)>>1;
        if(check(mid)){ANS=mid;r=mid-1;}
        else l=mid+1;
    }
    printf("%d\n",ANS);
    return 0;
}

T3,线段树+推式子。

p[i](il+1)(ri+1)

=i2p[i]+(l+r)ip[i](r+1)(l1)p[i]

线段树维护 i2p[i],ip[i],p[i] 的和即可

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#define N 100005
#define LL long long 
using namespace std;
LL lazy[N<<3],sum1[N<<3],sum2[N<<3],sum3[N<<3];
LL f[N],g[N];
LL n,q;
LL ans,mom,gg;
#define int long long 
void pushdown(LL rt,LL l,LL r){
    if(lazy[rt]){
        lazy[rt<<1]+=lazy[rt];
        lazy[rt<<1|1]+=lazy[rt];
        LL mid=(l+r)>>1;
        sum1[rt<<1]+=lazy[rt]*(mid-l+1);
        sum2[rt<<1]+=lazy[rt]*(f[mid]-f[l-1]);
        sum3[rt<<1]+=lazy[rt]*(g[mid]-g[l-1]);
        sum1[rt<<1|1]+=lazy[rt]*(r-mid);
        sum2[rt<<1|1]+=lazy[rt]*(f[r]-f[mid]);
        sum3[rt<<1|1]+=lazy[rt]*(g[r]-g[mid]);
        lazy[rt]=0;
    }
}
void pushup(LL rt,LL l,LL r){
    if(l==r)return;
    sum1[rt]=sum1[rt<<1]+sum1[rt<<1|1]+lazy[rt]*(r-l+1);
    sum2[rt]=sum2[rt<<1]+sum2[rt<<1|1]+lazy[rt]*(f[r]-f[l-1]);
    sum3[rt]=sum3[rt<<1]+sum3[rt<<1|1]+lazy[rt]*(g[r]-g[l-1]);
}
void update(LL rt,LL l,LL r,LL x,LL y,LL z){
    if(x<=l&&r<=y){
        lazy[rt]+=z;
        sum1[rt]+=z*(r-l+1);
        sum2[rt]+=z*(f[r]-f[l-1]);
        sum3[rt]+=z*(g[r]-g[l-1]);
        return ;
    }
    pushdown(rt,l,r);
    LL mid=(l+r)>>1;
    if(x<=mid) update(rt<<1,l,mid,x,y,z);
    if(y>mid) update(rt<<1|1,mid+1,r,x,y,z);
    pushup(rt,l,r);
}
void query(LL rt,LL l,LL r,LL x,LL y){
    if(x<=l&&r<=y){
        ans-=sum3[rt];
        ans+=(x+y)*sum2[rt];
        ans-=1ll*(y+1)*(x-1)*sum1[rt];
        return ;
    }
    pushdown(rt,l,r);
    LL mid=(l+r)>>1;
    if(x<=mid) query(rt<<1,l,mid,x,y);
    if(y>mid) query(rt<<1|1,mid+1,r,x,y);
}
LL gcd(LL a,LL b){
    return b==0?a:gcd(b,a%b);
}
signed main(){
    scanf("%lld%lld",&n,&q);
    for(int i=1;i<=n;i++){
        f[i]=f[i-1]+i;
        g[i]=g[i-1]+1ll*i*i;
    }
    char ch[3];
    for(int i=1,l,r,d;i<=q;i++){
        scanf("%s",ch);
        if(ch[0]=='C'){
            scanf("%lld%lld%lld",&l,&r,&d);
            update(1,1,n-1,l,r-1,d);
        }
        else{
            scanf("%lld%lld",&l,&r);
            ans=0; mom=(r-l+1)*(r-l)/2;
            query(1,1,n-1,l,r-1);
            gg=gcd(ans,mom);
            printf("%lld/%lld\n",ans/gg,mom/gg);
        }
    }
    return 0;
}

define int long long ……233

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值