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;
}