CSP模拟<反思> (21~31)
csp模拟21#
ARC141F#
首先上结论:如果一个串能用其他串消完那么这个串可以删去;
剩下的串中有
如果存在
第一部分:如何判断一个串
建 AC 自动机,预处理
第二部分,对筛选出来的串在 AC自动机里跑一边,记录每个点被经历的次数和被谁经历。如果经历次数大于 1,则答案为 Yes。
设
接着对于每个
不为 Yes 则为 No。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=2*1e6+10;
string s[N];
int tr[N][4],tot=0,fail[N],en[N],len[N],rk[N],d[N],idx[N],pk[N];
map<int,int>f[N];
int b[N];
bool vis[N];
int st[N],top;
int head[N],nex[N],ver[N],tot_node=0,mark[N][2];
queue<int> q;
void add(int x,int y){
ver[++tot_node]=y;nex[tot_node]=head[x],head[x]=tot_node;
}
void insert(string s1,int id){
int u=0;
for(int i=0;s1[i];i++){
int ch=s1[i]-'A';
if(!tr[u][ch]) tr[u][ch]=++tot;
d[tr[u][ch]]=d[u]+1;
u=tr[u][ch];
}
en[u]++;
rk[id]=u;
}
void build(){
for(int i=0;i<4;i++){
if(tr[0][i]){
add(0,tr[0][i]);
q.push(tr[0][i]);
}
}
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=0;i<4;i++){
if(tr[u][i]){
fail[tr[u][i]]=tr[fail[u]][i];
add(fail[tr[u][i]],tr[u][i]);
q.push(tr[u][i]);
}
else{
tr[u][i]=tr[fail[u]][i];
}
}
}
}
void dfs(int x,int f){
mark[x][0]=mark[f][0];
if(en[x]){
mark[x][0]=x;
mark[x][1]=mark[f][0];
}
for(int i=head[x];i;i=nex[i]){
int y=ver[i];
if(y==f) continue;
dfs(y,x);
}
}
void ask(string s1,int id){
int u=0;
for(int i=0;s1[i];i++){
int ch=s1[i]-'A';
u=tr[u][ch];
pk[u]=id;
idx[u]++;
}
}
void clear(int x){
tot=0,tot_node=0;
memset(tr,0,sizeof(tr));
memset(fail,0,sizeof(fail));
memset(mark,0,sizeof(mark));
memset(en,0,sizeof(en));
memset(len,0,sizeof(len));
memset(rk,0,sizeof(rk));
memset(d,0,sizeof(d));
memset(idx,0,sizeof(idx));
memset(pk,0,sizeof(pk));
memset(head,0,sizeof(head));
memset(nex,0,sizeof(nex));
memset(ver,0,sizeof(ver));
memset(vis,0,sizeof(vis));
for(int i=1;i<=x;i++){
f[i].clear();
}
}
int main(){
int T=1;
while(T--){
int n;
scanf("%d",&n);
clear(n);
for(int i=1;i<=n;i++){
cin>>s[i];
len[i]=s[i].size();
insert(s[i],i);
}
build();
dfs(0,0);
int getans=0;
for(int k=1;k<=n;k++){
int u=0;
top=0;
for(int i=0;i<len[k];i++){
u=tr[st[top]][s[k][i]-'A'];
st[++top]=u;
if(rk[k]!=u && mark[u][0]) top-=d[mark[u][0]];
if(rk[k]==u && mark[u][1]) top-=d[mark[u][1]];
}
if(top==0) vis[k]=1;
if(top && top<len[k]){
printf("Yes\n");
getans=1;
break;
}
}
if(getans) continue;
for(int i=1;i<=n;i++){
if(vis[i]) continue;
ask(s[i],i);
}
for(int i=1;i<=n;i++){
if(vis[i]) continue;
int tmp=rk[i];
int last=0;
while(fail[tmp]){
tmp=fail[tmp];
if(last==d[tmp]){
printf("Yes\n");
getans=1;
break;
}
f[i][d[tmp]]=pk[tmp];
last=d[tmp];
}
if(getans) break;
}
if(getans) continue;
for(int i=1;i<=n;i++){
if(vis[i]) continue;
int tmp=rk[i];
while(fail[tmp]){
tmp=fail[tmp];
int t=d[tmp];
int j=f[i][t];
if(!j) continue;
if(len[i]!=len[j] ||f[j][len[i]-t]!=i){
printf("Yes\n");
getans=1;
break;
}
}
if(getans) break;
}
if(getans) continue;
printf("No\n");
}
}
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=8*1e5+10;
int a[N],head[N*2],ver[N*2],nex[N*2],tot=0;
void add(int x,int y){
ver[++tot]=y,nex[tot]=head[x],head[x]=tot;
}
int d[N],top[N],fa[N],son[N],size[N],ed[N],id[N],cnt=0,rk[N];
struct asd{
int lazy;
int l,r;
int p,op;
int lmax,lmin;
int nmax,nmin;
}tr[N*4];
int lson[N],rson[N];
void dfs1(int x,int f){
fa[x]=f;
d[x]=d[f]+1;
size[x]=1;
if(lson[x]){
dfs1(lson[x],x);
size[x]+=size[lson[x]];
if(size[son[x]]<size[lson[x]]){
son[x]=lson[x];
}
}
if(rson[x]){
dfs1(rson[x],x);
size[x]+=size[rson[x]];
if(size[son[x]]<size[rson[x]]){
son[x]=rson[x];
}
}
}
void dfs2(int x,int tp){
id[x]=++cnt;
rk[cnt]=x;
top[x]=tp;
if(son[x]) dfs2(son[x],tp);
if(lson[x] && lson[x]!=son[x]){
dfs2(lson[x],lson[x]);
}
if(rson[x] && rson[x]!=son[x]){
dfs2(rson[x],rson[x]);
}
ed[x]=cnt;
}
void pushup(int p){
tr[p].lmax=max(tr[p*2].lmax,tr[p*2+1].lmax);
tr[p].lmin=min(tr[p*2].lmin,tr[p*2+1].lmin);
tr[p].nmax=max(tr[p*2].nmax,tr[p*2+1].nmax);
tr[p].nmin=min(tr[p*2].nmin,tr[p*2+1].nmin);
}
void pushdown(int p){
if(tr[p].lazy){
tr[p].lazy^=1;
tr[p*2].lazy^=1,tr[p*2+1].lazy^=1;
swap(tr[p*2].lmax,tr[p*2].nmax);
swap(tr[p*2].lmin,tr[p*2].nmin);
swap(tr[p*2+1].lmax,tr[p*2+1].nmax);
swap(tr[p*2+1].lmin,tr[p*2+1].nmin);
}
}
void build(int p,int l,int r){
tr[p].l=l,tr[p].r=r;
tr[p].lazy=0;
if(l==r){
if(lson[fa[rk[l]]]==rk[l]){
tr[p].nmin=a[fa[rk[l]]];tr[p].nmax=INT_MIN;
tr[p].lmax=a[fa[rk[l]]];tr[p].lmin=INT_MAX;
}
else{
tr[p].nmax=a[fa[rk[l]]];tr[p].nmin=INT_MAX;
tr[p].lmin=a[fa[rk[l]]];tr[p].lmax=INT_MIN;
}
return;
}
int mid=(l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
pushup(p);
}
int query(int p,int l,int r,int op){
if(tr[p].l>=l && tr[p].r<=r){
if(op==1) return tr[p].nmin;////////1 : small
else return tr[p].nmax;
}
pushdown(p);
int mid=(tr[p].l+tr[p].r)/2;
if(op==1){
int ans=INT_MAX;
if(l<=mid) ans=min(ans,query(p*2,l,r,op));
if(r>mid) ans=min(ans,query(p*2+1,l,r,op));
return ans;
}
else{
int ans=INT_MIN;
if(l<=mid) ans=max(ans,query(p*2,l,r,op));
if(r>mid) ans=max(ans,query(p*2+1,l,r,op));
return ans;
}
}
void change(int p,int wh,int v){
if(tr[p].l==tr[p].r){
if(tr[p].lmin==a[fa[rk[wh]]]) tr[p].lmin=v;
if(tr[p].lmax==a[fa[rk[wh]]]) tr[p].lmax=v;
if(tr[p].nmin==a[fa[rk[wh]]]) tr[p].nmin=v;
if(tr[p].nmax==a[fa[rk[wh]]]) tr[p].nmax=v;
return;
}
pushdown(p);
int mid=(tr[p].l+tr[p].r)/2;
if(wh<=mid) change(p*2,wh,v);
else change(p*2+1,wh,v);
pushup(p);
}
int ask_mi(int x){
int fx=top[x];
int ans=INT_MAX;
while(fx>1){
ans=min(ans,query(1,id[fx],id[x],1));
x=fa[fx],fx=top[x];
}
ans=min(ans,query(1,id[1]+1,id[x],1));
return ans;
}
int ask_ma(int x){
int fx=top[x];
int ans=INT_MIN;
while(fx>1){
ans=max(ans,query(1,id[fx],id[x],0));
x=fa[fx],fx=top[x];
}
ans=max(ans,query(1,id[1]+1,id[x],0));
return ans;
}
void chan(int p,int l,int r){
if(tr[p].l>=l && tr[p].r<=r){
tr[p].lazy^=1;
swap(tr[p].lmax,tr[p].nmax);
swap(tr[p].lmin,tr[p].nmin);
return;
}
pushdown(p);
int mid=(tr[p].l+tr[p].r)/2;
if(l<=mid) chan(p*2,l,r);
if(r>mid) chan(p*2+1,l,r);
pushup(p);
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
int x,y;
scanf("%d%d",&x,&y);
if(x)lson[i]=x;
if(y)rson[i]=y;
}
dfs1(1,0);
dfs2(1,0);
build(1,1,cnt);
for(int i=1;i<=m;i++){
int opt,x,y;
scanf("%d%d",&opt,&x);
if(opt==3){
int mi=ask_mi(x);
int ma=ask_ma(x);
if(a[x]>=mi || a[x]<=ma) printf("NO\n");
else printf("YES\n");
}
if(opt==1){
scanf("%d",&y);
if(lson[x]) change(1,id[lson[x]],y);
if(rson[x]) change(1,id[rson[x]],y);
a[x]=y;
}
if(opt==2){
chan(1,id[x]+1,ed[x]);
}
}
}
csp模拟24#
监狱#
首先得到一个结论,如果存在方案,一定有一种方案使每个人都是从起点不停歇地走到终点。因为如果一个合法方案中,
分析一下题目,发现限制只有两条:
- 如果
的起点在 的路径上,那么 必须先于 走。 - 如果
的终点在 的路径上,那么 必须先于 走。
那么将
我们首先将原图的树复制两棵
对于第
- 对于路径上的终点,
必须先于终点在这条路径上的人走,所以 节点连向这些点在 中的区间。 - 对于路径上的起点,这些点必须先于
先走,所以 这些点在 中的区间连向 。 - 为了传递限制,还需对每个
向 连边( 为叶子节点编号, 为该节点上的起点)。 - 为了传递限制,还需对每个
向 连边( 为叶子节点编号, 为该节点上的终点)。
可以对原树树剖,边跳
当然这里也可以用倍增优化建图做路径连边,复杂度
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=120005;
const int M=N*50;
int s[N],t[N];
int pi[N],du[M];
int head[N*2],ver[N*2],nex[N*2],tot=0;
void add(int x,int y){
ver[++tot]=y,nex[tot]=head[x],head[x]=tot;
}
int head_t[M],ver_t[M],nex_t[M],tot_t=0;
void add_t(int x,int y){
ver_t[++tot_t]=y,nex_t[tot_t]=head_t[x],head_t[x]=tot_t;
du[y]++;
}
int fa[N],top[N],siz[N],d[N],son[N],id[N],tot_d=0;
int cnt_t,rt1,rt2;
void dfs1(int x,int f){
fa[x]=f;
siz[x]=1;
d[x]=d[f]+1;
for(int i=head[x];i;i=nex[i]){
int y=ver[i];
if(y==f) continue;
dfs1(y,x);
siz[x]+=siz[y];
if(siz[son[x]]<siz[y]){
son[x]=y;
}
}
}
void dfs2(int x,int tp){
top[x]=tp;
id[x]=++tot_d;
// rk[tot_d]=x;
if(son[x]) dfs2(son[x],tp);
for(int i=head[x];i;i=nex[i]){
int y=ver[i];
if(y==fa[x]) continue;
if(y!=son[x]) dfs2(y,y);
}
}
struct Segment_tree{
int l,r;
}tr[M];
int S[N],T[N];
void buildt(int &p,int l,int r){
if(!p) p=++cnt_t;
if(l==r){
T[l]=p;
return;
}
int mid=(l+r)/2;
buildt(tr[p].l,l,mid);
buildt(tr[p].r,mid+1,r);
add_t(p,tr[p].l);
add_t(p,tr[p].r);
}
void builds(int &p,int l,int r){
if(!p) p=++cnt_t;
if(l==r){
S[l]=p;
return;
}
int mid=(l+r)/2;
builds(tr[p].l,l,mid);
builds(tr[p].r,mid+1,r);
add_t(tr[p].l,p);
add_t(tr[p].r,p);
}
void changet(int p,int wh,int l,int r,int id){
if(l==r){
add_t(p,pi[id]);
return;
}
int mid=(l+r)/2;
if(wh<=mid) changet(tr[p].l,wh,l,mid,id);
else changet(tr[p].r,wh,mid+1,r,id);
}
void changes(int p,int wh,int l,int r,int id){
if(l==r){
add_t(pi[id],p);
return;
}
int mid=(l+r)/2;
if(wh<=mid) changes(tr[p].l,wh,l,mid,id);
else changes(tr[p].r,wh,mid+1,r,id);
}
void changet1(int p,int l,int r,int L,int R,int id){
if(l>r) return;
if(L>=l && R<=r){
add_t(pi[id],p);
return;
}
int mid=(L+R)/2;
if(l<=mid) changet1(tr[p].l,l,r,L,mid,id);
if(r>mid) changet1(tr[p].r,l,r,mid+1,R,id);
}
void changes1(int p,int l,int r,int L,int R,int id){
if(l>r) return;
if(L>=l && R<=r){
add_t(p,pi[id]);
return;
}
int mid=(L+R)/2;
if(l<=mid) changes1(tr[p].l,l,r,L,mid,id);
if(r>mid) changes1(tr[p].r,l,r,mid+1,R,id);
}
void workt(int x,int y,int op){
int fx=top[x],fy=top[y];
while(fx!=fy){
if(d[fx]>d[fy]){
int as=id[fx],bs=id[x];
changet1(rt1,as,bs,1,tot_d,op);
if(x==s[op]) changes1(rt2,as,bs-1,1,tot_d,op);
else changes1(rt2,as,bs,1,tot_d,op);
x=fa[fx],fx=top[x];
}
else{
int as=id[fy],bs=id[y];
if(y==t[op]) changet1(rt1,as,bs-1,1,tot_d,op);
else changet1(rt1,as,bs,1,tot_d,op);
changes1(rt2,as,bs,1,tot_d,op);
y=fa[fy],fy=top[y];
}
}
int as=id[x],bs=id[y];
if(id[x]<id[y]){
if(y==t[op]) bs--;
changet1(rt1,id[x],bs,1,tot_d,op);
if(x==s[op]) as++;
changes1(rt2,as,id[y],1,tot_d,op);
}
else{
if(y==t[op]) bs++;
changet1(rt1,bs,id[x],1,tot_d,op);
if(x==s[op]) as--;
changes1(rt2,id[y],as,1,tot_d,op);
}
}
queue<int> q;
void clear(int n,int m){
for(int i=1;i<=cnt_t;i++) head_t[i]=du[i]=0;
for(int i=1;i<=n;i++) head[i]=siz[i]=son[i]=fa[i]=top[i]=siz[i]=d[i]=id[i]=0;
for(int i=1;i<=m;i++) pi[i]=s[i]=t[i]=0;
for(int i=1;i<=cnt_t;i++){
tr[i].l=tr[i].r=0;
}
tot=tot_t=tot_d=cnt_t=0;
rt1=rt2=0;
}
signed main(){
// freopen("prison.in","r",stdin);
// freopen("prison.out","w",stdout);
int pp;
scanf("%d",&pp);
while(pp--){
int n;
scanf("%d",&n);
for(int i=1;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
add(x,y),add(y,x);
}
dfs1(1,0);
dfs2(1,0);
cnt_t=0;
buildt(rt1,1,tot_d);
builds(rt2,1,tot_d);
int m;
scanf("%d",&m);
for(int i=1;i<=m;i++){
pi[i]=++cnt_t;
}
for(int i=1;i<=m;i++){
scanf("%d%d",&s[i],&t[i]);
changet(rt1,id[t[i]],1,tot_d,i);
changes(rt2,id[s[i]],1,tot_d,i);
}
for(int i=1;i<=m;i++){
workt(s[i],t[i],i);
}
for(int i=1;i<=cnt_t;i++){
if(du[i]==0){
q.push(i);
}
}
while(!q.empty()){
int x=q.front();
q.pop();
for(int i=head_t[x];i;i=nex_t[i]){
int y=ver_t[i];
du[y]--;
if(du[y]==0) q.push(y);
}
}
int ans=0;
for(int i=1;i<=m;i++){
if(du[pi[i]]) {
ans=1;
break;
}
}
if(ans==1) printf("No\n");
else printf("Yes\n");
clear(n,m);
}
}
[AGC023E] Inversions#
再补充一点点:
对于
对于
取模取尽
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=4*1e5+5;
const int mod=1e9+7;
int a[N],cnt[N],sum[N];
int prod[N];
int n;
int c[N],d[N];
int mgml(int x,int p){
int ans=1;
while(p){
if(p&1) ans=(ans*x)%mod;
x=(x*x)%mod;
p>>=1;
}
return ans;
}
int lowbit(int x){
return x&(-x);
}
void add(int x,int v){
for(;x<=N;x+=lowbit(x)) c[x]=(c[x]+v)%mod;
}
int ask(int x){
if(x<=0) return 0;
int ans=0;
for(;x;x-=lowbit(x)) ans=(ans+c[x])%mod;
return ans;
}
void add_1(int x,int v){
for(;x<=N;x+=lowbit(x)) d[x]=(d[x]+v)%mod;
}
int ask_1(int x){
if(x<=0) return 0;
int ans=0;
for(;x;x-=lowbit(x)) ans=(ans+d[x])%mod;
return ans;
}
int nex0[N];
signed main(){
scanf("%lld",&n);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
sum[a[i]]++;
}
int tot=1;
for(int i=n;i>=1;i--){
sum[i]=(sum[i]+sum[i+1])%mod;
cnt[i]=sum[i]-(n-i);
tot=tot*cnt[i]%mod;
}
prod[0]=1;
for(int i=1;i<=n;i++){
int sum=(cnt[i]-1)*mgml(cnt[i],mod-2)%mod;
prod[i]=prod[i-1]*sum%mod;
if(cnt[i]==1){
while(cnt[i]==1){
i++;
}
prod[i]=(cnt[i]-1)*mgml(cnt[i],mod-2)%mod;
}
}
int wh=n+1;
for(int i=n;i>=1;i--){
if(prod[i]==0) wh=i;
nex0[i]=wh;
}
int ans=0;
for(int i=n;i>=1;i--){
int sum=(ask(nex0[a[i]])-ask(a[i]-1)+mod)%mod;
ans=(ans+sum*mgml(prod[a[i]],mod-2)%mod)%mod;
add(a[i],prod[a[i]]);
}
ans=(ans*tot%mod*mgml(2,mod-2)%mod+mod)%mod;
int anss=0;
memset(c,0,sizeof(c));
for(int i=1;i<=n;i++){
int sum=(ask(nex0[a[i]])-ask(a[i])+mod)%mod;
int to=(ask_1(n)-ask_1(a[i])+mod)%mod;
int cnt=(tot*to%mod-tot*sum%mod*mgml(prod[a[i]]*2%mod,mod-2)%mod+mod)%mod;
anss=(anss+cnt)%mod;
add(a[i],prod[a[i]]);
add_1(a[i],1);
}
cout<<(ans+anss+mod)%mod;
}
csp模拟29#
坍缩#
学到了对于字符串回文的处理。
对每个字符定义
竖着得字符串对每个字符出现次数进行
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=993244853;
char s[300][300];
int has[300];
int f[300],g[300];
int _xorhas[300];
bool flat[300];
int min(int a,int b){
return a<b?a:b;
}
int manacher(int n){
int ans=0;
memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
for(int i=1,l=0,r=-1;i<=n;++i){
if(flat[i]) continue;
int k;
if(i>r) k=1;
else k=min(r-i+1,f[r+l-i]);
while( i-k>=1 && i+k<=n &&has[i-k]==has[i+k] && flat[i-k]==0 && flat[i+k]==0) k++;
f[i]=k--;
ans+=f[i];
if(r<i+k){
r=i+k;
l=i-k;
}
}
for(int i=1,l=0,r=-1;i<=n;++i){
if(flat[i] || flat[i-1]) continue;
int k;
if(i>r) k=0;
else k=min(r-i+1,g[l+r-i+1]);
while(i-k-1>=1 && i+k<=n && has[i-k-1]==has[i+k] && flat[i-k-1]==0 && flat[i+k]==0) k++;
g[i]=k--;
ans+=g[i];
if(r<i+k){
r=i+k;
l=i-k-1;
}
}
return ans;
}
int p(char x){
return (1<<(x-'a'));
}
int sum[300][300];
int sum1[300][300];
int base[30];
int po[30];
signed main(){
int n,m;
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++){
scanf("%s",s[i]+1);
}
po[0]=1;
for(int i=1;i<=26;i++){
po[i]=po[i-1]*113%mod;
}
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
sum[i][j]=sum[i][j-1]^(1ll<<(s[i][j]-'a'));
sum1[i][j]=(sum1[i][j-1]+po[s[i][j]-'a'])%mod;
}
}
int ans=0;
for(int i=1;i<=m;++i){
for(int j=i;j<=m;++j){
for(int k=1;k<=n;++k){
flat[k]=0;
int hass=(sum1[k][j]-sum1[k][i-1]+mod)%mod;
int xo=sum[k][j]^sum[k][i-1]%mod;
has[k]=hass;
if(__builtin_popcountll(xo)>1) flat[k]=1;
}
ans+=manacher(n);
}
}
printf("%lld",ans);
}
csp模拟30#
AT_agc019_f [AGC019F] Yes or No#
假设
这张图是对于当前局势我们进行的最优决策,然而答案并不是这个样子,而你答对的题数是原本答案折线与红线重合部分,思考发现一定有
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=998244353;
const int N=1e6+5;
int mgml(int x,int p){
int ans=1;
while(p){
if(p&1) ans=(ans*x)%mod;
x=(x*x)%mod;
p>>=1;
}
return ans;
}
int fac[N],ifac[N];
int n,m;
void init(){
fac[0]=ifac[0]=1;
for(int i=1;i<=n+m;i++){
fac[i]=fac[i-1]*i%mod;
ifac[i]=mgml(fac[i],mod-2);
}
}
int C(int x,int y){
return fac[x]*ifac[x-y]%mod*ifac[y]%mod;
}
signed main(){
scanf("%lld%lld",&n,&m);
if(n>m) swap(n,m);
int sum=0;
init();
for(int i=1;i<=n;i++){
sum+=C(2*i,i)*C(n+m-2*i,n-i)%mod;
sum%=mod;
}
cout<<(sum*mgml(2,mod-2)%mod*mgml(C(n+m,n)%mod,mod-2)%mod+m)%mod;
}
枫#
还是对这种约瑟夫似的问题偏弱。
对于一个长度为
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=7*1e6+5;
int a[N];
bool flat[N];
int q,m;
int ans[N];
signed main(){
int T;
scanf("%lld",&T);
for(int k=1;k<=T;++k){
scanf("%lld%lld",&q,&m);
ans[1]=1;
for(int i=2;i<=m;i++){
int last=i-1-(i-1)/(k+1);
int p=last-ans[last]+1;
ans[i]=p+1+(p-1)/k;
}
for(int i=1;i<=q;i++){
int x;
scanf("%lld",&x);
printf("%lld ",ans[x]);
}
printf("\n");
}
}
/*
1
7 10 6
*/
楼房重建#
很神奇的线段树
线段树上维护区间最大值
合并左右儿子时,做儿子的答案是一定要的,设左儿子最大值为
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
struct asd{
int l,r,sum;
double ma;
}tr[N*4];
void build(int p,int l,int r){
tr[p].l=l;tr[p].r=r;
tr[p].ma=0;
if(l==r) return;
int mid=(l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
}
int pushup(double ma,int p){
if(tr[p].l==tr[p].r) return tr[p].ma>ma;
if(tr[p*2].ma<=ma) return pushup(ma,p*2+1);
else return pushup(ma,p*2)+tr[p].sum-tr[p*2].sum;
}
void change(int p,int wh,double v){
if(tr[p].l==tr[p].r){
tr[p].sum=1,tr[p].ma=v;
return;
}
int mid=(tr[p].l+tr[p].r)/2;
if(wh<=mid) change(p*2,wh,v);
else change(p*2+1,wh,v);
tr[p].ma=max(tr[p*2].ma,tr[p*2+1].ma);
tr[p].sum=tr[p*2].sum+pushup(tr[p*2].ma,p*2+1);
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
build(1,1,n);
for(int i=1;i<=m;i++){
double x,y;
scanf("%lf%lf",&x,&y);
change(1,x,y/x);
int ans=tr[1].sum;
printf("%d\n",ans);
}
}
csp模拟31#
你相信引力吗#
很巧妙的一道单调栈问题。
首先它是一个递减栈,加入一个元素,如果它比栈顶元素大,那么弹栈并记录贡献,因为是显然的。最后将其
作者:bloss
出处:https://www.cnblogs.com/jinjiaqioi/p/17632365.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】