每日二三题

142 篇文章 0 订阅
142 篇文章 1 订阅

div2 加一

加一 - 题目 - Daimayuan Online Judge

我的思路是开一个数组num记录0-9的个数,从10这个数开始枚举m=1到2e5可以到达的长度,可以知道每枚举一次只要把0-9的个数加起来就是当前阶段的长度,重点是要如何转移num中0-9的个数,每枚举一次每个数都是要+1的,那么num[i]不就是num[i-1]吗?然后会有个特例,num[1]=num[9]+num[0],num[0]=num[9];这个也很好理解,预处理完就直接开干就完了;

大佬的思路是用的dp做的,dp[i][j]代表对j操作i次可以到达的长度,那么就会有方程

dp[i+1][j-1]=dp[i][j];

还需要注意的是9这个数

dp[i+1][9]=dp[i][0]+dp[i][1]; 因为9到1,0是需要操作1次的

 下面是大佬的dp代码

#include<bits/stdc++.h>
using namespace std;

const int N=200010,MOD=1e9+7;
typedef long long LL;

int m,ans,len;
LL dp[N][10];
char n[15];

void init()
{
	for (int i=0;i<=9;i++)	dp[0][i]=1;
	for (int i=0;i<N;i++)
	{
		for (int j=1;j<=9;j++)	dp[i+1][j-1]=dp[i][j];	
		dp[i+1][9]=(dp[i][0]%MOD+dp[i][1]%MOD)%MOD;
	}
}

int main()
{
	int t;scanf("%d",&t);
	init();
	while(t--)
	{
		scanf("%s%d",&n,&m);	
		ans=0;len=strlen(n);
		for (int i=0;i<len;i++)
			ans=(ans+dp[m][n[i]-'0'])%MOD;
		printf("%d\n",ans%MOD);
	}	
	return 0;
}

下面是在下的代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
ll qpow(ll a,ll b){
    ll res=1;
    while(b){
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}
ll t,m,num[10],cnt[200005]={0};
char n[110];
void init(){
    num[0]=num[1]=1;
    for(int i=1;i<=2e5;i++){
        ll tmp=num[9];
        for(int j=9;j>=2;j--)
        num[j]=num[j-1]%mod;
        num[1]=(num[0]+tmp)%mod;
        num[0]=tmp%mod;
        for(int j=0;j<=9;j++) cnt[i]=(cnt[i]+num[j])%mod;
    }
}
int main(){
    //freopen("in.txt","r",stdin);
    init();
    scanf("%lld",&t);
    while(t--){
        ll ans=0;
        scanf("%s%lld",n+1,&m);
        for(int i=1;i<=strlen(n+1);i++){

            int x=n[i]-'0';ll y=10-x;
            //cout<<"cnt "<<cnt[m-10+x]<<" "<<ans<<endl;
            if(m<y) ans=(ans+1LL)%mod;
            else if(m==y) ans=(ans+2LL)%mod;
            else if(m>y) ans=(ans+cnt[m-y])%mod;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

p1714   单调队列维护前缀和

瞎搞才得了80,最后一个点怎么也不对,最后看题解才知道要单调队列维护前缀和,,,

题解 P1714 【切蛋糕】 - 繁凡さん的博客 - 洛谷博客 (luogu.org)

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
ll qpow(ll a,ll b){
    ll res=1;
    while(b){
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}
ll n,m,sum[500005],maxx=-10;
ll a[500005];
deque<ll>q;
int main(){
    //freopen("in.txt","r",stdin);
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
        sum[i]=sum[i-1]+a[i];
    }
    q.push_back(0);
    for(int i=1;i<=n;i++){
        while(q.size()>0&&q.front()+m<i) q.pop_front();
    //  上一行之所以没有等号是考虑到一开始入队的是0,要是有等号的话,下面就是
    //  q.back()-1了,那就数组越界了        
        maxx=max(maxx,sum[i]-sum[q.front()]);
        while(!q.empty()&&sum[q.back()]>=sum[i])//维护一个递增的数列才能得到最优解
        // 验证数据 3 3  1 -2 3
           q.pop_back();
        q.push_back(i);
    }
    printf("%lld\n",maxx);
    return 0;
}

p3369 权值线段树模板

【权值线段树+主席树-哔哩哔哩】 https://b23.tv/Xdrn46Q

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
ll qpow(ll a,ll b){
    ll res=1;
    while(b){
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}
ll n;
struct quer{
    ll q,x;
}qu[100005];
ll b[100005],num;
struct Node{
    ll l,r,val;
}t[100005<<2];
void build(ll rt,ll l,ll r){
    t[rt].l=l,t[rt].r=r,t[rt].val=0;
    if(l==r) return;
    ll mid=l+r>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
}
void update(ll rt,ll x,ll p){
    if(t[rt].l==t[rt].r){
        t[rt].val+=p;
        return;
    }
    ll mid=t[rt].l+t[rt].r>>1;
    if(x<=mid) update(rt<<1,x,p);
    else update(rt<<1|1,x,p);
    t[rt].val=t[rt<<1].val+t[rt<<1|1].val;
}
//查询排名是几
ll query(ll rt,ll l,ll r){
    if(t[rt].l>=l&&t[rt].r<=r) return t[rt].val;
    ll mid=t[rt].l+t[rt].r>>1;
    ll ans=0;
    if(l<=mid) ans+=query(rt<<1,l,r);
    if(r>mid) ans+=query(rt<<1|1,l,r);
    //上面的if必须要写,不然会有错误
    return ans;
}
//查询排名为x的数是多少
ll requery(ll rt,ll len){
    if(t[rt].l==t[rt].r) return t[rt].l;
    if(len<=t[rt<<1].val) return requery(rt<<1,len);
    else return requery(rt<<1|1,len-t[rt<<1].val);
}
int main(){
    //freopen("in.txt","r",stdin);
    scanf("%lld",&n);
    build(1,1,1e5);
    for(int i=1;i<=n;i++){
        scanf("%lld%lld",&qu[i].q,&qu[i].x);
        if(qu[i].q!=4)
        b[++num]=qu[i].x;
    }
    sort(b+1,b+num+1);
    num=unique(b+1,b+num+1)-b-1;
    for(int i=1;i<=n;i++){
        ll x=qu[i].x;
        if(qu[i].q!=4){
            x=lower_bound(b+1,b+num+1,x)-b;
        }
        ll ans;
        if(qu[i].q==1) update(1,x,1);
        else if(qu[i].q==2) update(1,x,-1);
        else if(qu[i].q==3){ans=query(1,1,x-1),ans++;printf("%lld\n",ans);}
        else if(qu[i].q==4){ans=requery(1,x);printf("%lld\n",b[ans]);}
        else if(qu[i].q==5){ans=query(1,1,x-1);ans=requery(1,ans);printf("%lld\n",b[ans]);}
        else if(qu[i].q==6){ans=query(1,1,x);ans=requery(1,ans+1);printf("%lld\n",b[ans]);}
    }
    return 0;
}


p3919 可持续化线段树模板2

简单的静态查询区间第k大,要了老命了,,,

(6条消息) 可持续化线段树_shi_zi_183的博客-CSDN博客_可持续化线段树

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
ll qpow(ll a,ll b){
    ll res=1;
    while(b){
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}
ll top=0,a[200005],b[200005],root[200005];
struct node{
    ll l,r,val;
}t[200005<<5];
ll update(ll pre,ll pl,ll pr,ll x){
    ll p=++top;
    t[p].l=t[pre].l;
    t[p].r=t[pre].r;
    t[p].val=t[pre].val+1;//新的树在原先的树的基础上这个数就多出现了一次,所以要加1
    ll mid=pl+pr>>1;
    if(pl<pr){
        if(x<=mid) t[p].l=update(t[p].l,pl,mid,x);//去更新左孩子
        else t[p].r=update(t[p].r,mid+1,pr,x);//更新右孩子
    }
    return p;
}
ll query(ll u,ll v,ll pl,ll pr,ll k){
    if(pl==pr) return pl;
    //v这个节点的左端点以前的数的个数减去u这个节点以前的数的个数,就是这个区间内的个数
    ll x=t[t[v].l].val-t[t[u].l].val;
    ll mid=pl+pr>>1;
    if(x>=k) return query(t[u].l,t[v].l,pl,mid,k);//逐渐缩小区间
    else return query(t[u].r,t[v].r,mid+1,pr,k-x);//因为左边已经有x个了,右边只需要查k-x个就行
}
int main(){
    //freopen("in.txt","r",stdin);
    ll n,m;
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]),b[i]=a[i];
    sort(b+1,b+n+1);
    ll num=unique(b+1,b+n+1)-b-1;
    for(int i=1;i<=n;i++){
        ll x=lower_bound(b+1,b+1+num,a[i])-b;
        root[i]=update(root[i-1],1,num,x);
    }
    while(m--){
        ll x,y,k;
        scanf("%lld%lld%lld",&x,&y,&k);
        ll ans=query(root[x-1],root[y],1,num,k);
        printf("%lld\n",b[ans]);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

killer_queen4804

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值