Redis-Redis及其持久化。
阿新 • • 發佈:2020-10-22
感謝卡老師上課分享的題單
CF558E
題意
Luogu
給定一個長度不超過10^5的字串(小寫英文字母),和不超過50000個操作。
每個操作 L R K 表示給區間[L,R]的字串排序,K=1為升序,K=0為降序。
輸出最終的字串。
題解
因為字符集只有26,所以區間內重複元素個數很多,排序後相同元素會聚攏,即區間覆蓋
考慮用線段樹記錄區間內每個字母出現的次數,然後按序區間覆蓋即可
程式碼
#include<bits/stdc++.h> using namespace std; #define re register #define ll long long #define get getchar() #define in inline in int read() { int t=0, x=1; char ch=get; while((ch<'0' || ch>'9') && ch!='-')ch=get; if(ch=='-') ch=get, x=-1; while(ch<='9' && ch>='0') t=t*10+ch-'0', ch=get; return x*t; } const int _=1e5+5; int n,m; char s[_]; int t[_<<3][27],la[_<<3],ans[27]; in void add(int k,int l,int r,int x,int y) { if(l==r) { t[k][y]++; return; } int mid=l+r>>1; if(x<=mid) add(k<<1, l, mid, x, y); else add(k<<1|1, mid+1, r, x, y); t[k][y]=t[k<<1][y]+t[k<<1|1][y]; } in void pushdown(int k,int l,int r) { if(la[k]==0) return ; la[k<<1]=la[k<<1|1]=la[k]; for(re int i=1;i<=26;i++) t[k<<1][i]=t[k<<1|1][i]=0; int mid=l+r>>1; t[k<<1][la[k]]=mid-l+1; t[k<<1|1][la[k]]=r-mid; la[k]=0; } in void query(int k,int l,int r,int x,int y) { if(x<=l && r<=y) { for(re int i=1;i<=26;i++) ans[i]+=t[k][i]; return; } int mid=l+r>>1; pushdown(k,l,r); if(x<=mid) query(k<<1, l, mid, x, y); if(y>mid) query(k<<1|1, mid+1, r, x, y); } in void update(int k,int l,int r,int x,int y,int z) { if(x<=l && r<=y) { for(re int i=1;i<=26;i++) t[k][i]=0; t[k][z]=r-l+1; la[k]=z; return; } pushdown(k,l,r); int mid=l+r>>1; if(x<=mid) update(k<<1, l, mid, x, y, z); if(y>mid) update(k<<1|1, mid+1, r, x, y, z); for(re int i=1;i<=26;i++) t[k][i]=t[k<<1][i]+t[k<<1|1][i]; } int main() { n=read(), m=read(); scanf("%s",s+1); for(re int i=1;i<=n;i++) add(1,1,n,i,s[i]-'a'+1); for(re int i=1;i<=m;i++) { int l=read(), r=read(), z=read(); query(1,1,n,l,r); int p=l; if(z==1) for(re int j=1;j<=26;j++) { if(ans[j]==0) continue; update(1,1,n,p,p+ans[j]-1,j); p+=ans[j]; } else for(re int j=26;j>=1;j--) { if(ans[j]==0) continue; update(1,1,n,p,p+ans[j]-1,j); p+=ans[j]; } memset(ans,0,sizeof(ans)); } for(re int i=1;i<=n;i++) { query(1,1,n,i,i); int k=0; for(re int j=1;j<=26;j++) if(ans[j]) {k=j;break;} //極其愚蠢的輸出方式:查詢每個點的字符集,找那個字元有值/kk ans[k]=0; printf("%c",char(k-1+'a')); } return 0; }
CF438D
題意
Luogu
給定數列,區間查詢和,區間取模,單點修改。
題解
老套路了
因為取模次數有限,最多log次
考慮暴力修改,並記錄區間最大值,當最大值小於模數時直接跳過
#include<bits/stdc++.h> using namespace std; #define re register #define ll long long #define get getchar() #define in inline in int read() { int t=0, x=1; char ch=get; while((ch<'0' || ch>'9') && ch!='-') ch=get; if(ch=='-') ch=get, x=-1; while(ch<='9' && ch>='0') t=t*10+ch-'0', ch=get; return t*x; } const int _=2e5+1; int n,m,mx[_<<4]; ll sum[_<<4]; in void pushup(int k) { sum[k]=sum[k<<1]+sum[k<<1|1]; mx[k]=max(mx[k<<1],mx[k<<1|1]); } in void add(int k,int l,int r,int x,int y) { if(l==r) { mx[k]=sum[k]=y; return ; } int mid=l+r>>1; if(x<=mid) add(k<<1, l, mid, x, y); else add(k<<1|1, mid+1, r, x, y); pushup(k); } in void mod(int k,int l,int r,int x,int y,int p) { if(mx[k]<p) return; //區間最大值小於模數 if(l==r) { mx[k]=sum[k]%=p; return; } int mid= l+r>>1; if(x<=mid) mod(k<<1, l, mid, x, y, p); if(y>mid) mod(k<<1|1, mid+1, r, x, y, p); pushup(k); } in ll query(int k,int l,int r,int x,int y) { if(x<=l && r<=y) return sum[k]; int mid=l+r>>1; ll s=0; if(x<=mid) s+=query(k<<1, l, mid, x, y); if(y>mid) s+=query(k<<1|1, mid+1, r, x, y); return s; } int main() { n=read(), m=read(); for(re int i=1;i<=n;i++) add(1,1,n,i,read()); for(re int i=1;i<=m;i++) { int opt=read(); if(opt==1) { int l=read(), r=read(); printf("%lld\n",query(1,1,n,l,r)); } if(opt==2) { int l=read(), r=read(), p=read(); mod(1,1,n,l,r,p); } if(opt==3) { int x=read(), y=read(); add(1,1,n,x,y); } } return 0; }