CSP-S模拟题(补几天的坑,62~69)

Posted heoitys

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CSP-S模拟题(补几天的坑,62~69)相关的知识,希望对你有一定的参考价值。

模拟62

   Graph

    很显然的一个性质是旅行次数为一个联通块中边数/2向下取整,树DP+贪心走一边DFS即可求出方案

技术图片
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> P;
typedef pair<P,int> D;
struct edge{
    int u,v;
    inline int get(int x){return x==u?v:u;}
}e[200050];
int N,M,last=0;
bool vis[100050],used[200050];
vector<int>to[100050];
vector<D>ans;
void dfs(int u,int pre){
    vis[u]=1;
    for(int i=0,y,v;i<to[u].size();++i){
        y=to[u][i];v=e[y].get(u);
        if(vis[v])continue;dfs(v,y);
    }
    for(int i=0,y,v;i<to[u].size();++i){
        y=to[u][i];v=e[y].get(u);
        if(used[y]||y==last||y==pre)continue;
        if(last)ans.push_back(D(P(e[last].get(u),v),u)),used[last]=1,used[y]=1,last=0;else last=y;
    }
    if(last&&pre){
        ans.push_back(D(P(e[last].get(u),e[pre].get(u)),u)),used[last]=1,used[pre]=1,last=0;
    }
}

int main(){
    cin>>N>>M;
    for(int i=1,u,v;i<=M;++i)scanf("%d%d",&u,&v),to[u].push_back(i),to[v].push_back(i),e[i].u=u,e[i].v=v;
    for(int i=1;i<=N;++i){
        last=0;
        if(!vis[i])dfs(i,0);
    }
    cout<<ans.size()<<endl;
    for(int i=0;i<ans.size();++i)cout<<ans[i].first.first<<" "<<ans[i].second<<" "<<ans[i].first.second<<endl;
}
/*
4 5
1 2
3 2
2 4
3 4
4 1

*/
View Code

  Permutation 好题

    正串最小,反串最大(不会证明),解法是建边跑拓扑排序

技术图片
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
int n,k,p[510000],q[510000],to[1010000],nex[1010000],head[510000],indu[510000],tot;
int minn[2010000];
struct node{
    int x;
    bool operator < (const node b)const{
        return x>b.x;
    }
};
priority_queue<node>qwq;
void add(int x,int y){
    to[++tot]=y,nex[tot]=head[x],head[x]=tot;
    indu[y]++;
}
void add_point(int t,int l,int r,int x,int k){
    if(l==r){
        minn[t]=k;
        return;
    }
    int mid=(l+r)>>1;
    if(mid>=x) add_point(t*2,l,mid,x,k);
    else add_point(t*2+1,mid+1,r,x,k);
    minn[t]=min(minn[t*2],minn[t*2+1]);
}
int query(int t,int l,int r,int L,int R){
    if(L>R) return n+1;
    if(L<=l&&r<=R){
        return minn[t];
    }
    int mid=(l+r)>>1,ans=n+1;
    if(mid>=L) ans=min(ans,query(t*2,l,mid,L,R));
    if(mid<R) ans=min(ans,query(t*2+1,mid+1,r,L,R));
    return ans;
}
void build(int t,int l,int r){
    minn[t]=n+1;
    if(l==r) return;
    int mid=(l+r)>>1;
    build(t*2,l,mid);
    build(t*2+1,mid+1,r);
}
int main(){
    scanf("%d%d",&n,&k);
    for(register int i=1;i<=n;i++) scanf("%d",&p[i]),q[p[i]]=i;
    build(1,1,n);
    for(register int i=n;i>=1;i--){
        int x=query(1,1,n,max(1,q[i]-k+1),q[i]),y=query(1,1,n,q[i],min(n,q[i]+k-1));
        if(x<=n) add(q[i],q[x]);
        if(y<=n) add(q[i],q[y]);
        add_point(1,1,n,q[i],i);
    }
    for(register int i=1;i<=n;i++) if(indu[i]==0) qwq.push((node){i});
    int tm=0;
    while(qwq.size()){
        int x=qwq.top().x;qwq.pop();
        q[++tm]=x;
        for(register int i=head[x];i;i=nex[i]){
            int y=to[i];
            indu[y]--;
            if(indu[y]==0) qwq.push((node){y});
        }
    }
    for(register int i=1;i<=n;i++) p[q[i]]=i;
    for(register int i=1;i<=n;i++) printf("%d
",p[i]);
    
    
}
View Code

  Tree

    考虑让经过最小边的路径最少使得答案最大,那么可以发现是能够只走一次最小边,向下划分子问题,最后答案就是~边权和(-_- !)

技术图片
#include<iostream>
#include<cstdio>
using namespace std;
int n;
long long ans;
int main(){
    //freopen("3.in","r",stdin);
    //freopen("3.out","w",stdout);
    scanf("%d",&n);
    for(register int i=1,x,y,z;i<n;i++){
        scanf("%d%d%d",&x,&y,&z);
        ans+=z;
    }
    printf("%lld
",ans);
}
View Code

模拟 63

  Median 好题

    离散化,数据可以看成是随机的,然后开桶记录数出现的次数,移动窗口的同时移动中位数,只是千万别sort(我不知道,我没改完,我被停  训了~因为没值日)

技术图片
#include<bits/stdc++.h>
using namespace std;
int n,k,w;
long long tmp[11000000],S[11000000],prm[11000000],l,r,num1,num2;
char vis[110000000];
void move_right(){num1++,num2--,l++;while(tmp[l]==0&&l<=n) l++;}
void move_left(){num1--,num2++,l--;while(tmp[l]==0&&l) l--;}
struct node{
    int x,id,dis;
}p[11000000];
char cmp1(node a,node b){
    return a.x<b.x;
}
char cmp2(node a,node b){
    return a.id<b.id;
}
int main(){
    //freopen("1.in","r",stdin);
    //freopen("2.out","w",stdout);
    scanf("%d%d%d",&n,&k,&w);
    for(register int i=2;i<=100000000;i++){
        if(!vis[i]) prm[++prm[0]]=i;
        for(register int j=1;j<=prm[0]&&i*prm[j]<=100000000;j++){
            vis[i*prm[j]]=1;
            if(i%prm[j]==0) break;
        }
        if(prm[0]==n) break;
    }
    for(register int i=1;i<=n;i++){
        S[i]=prm[i]*i%w;
        p[i].x=S[i]+S[(int)floor(1.0*i/10.0)+1];
        p[i].id=i;
    }
    sort(p+1,p+n+1,cmp1);
    for(register int i=1;i<=n;i++){
        p[i].dis=i,S[i]=p[i].x;
    }
    sort(p+1,p+n+1,cmp2);
    double ans=0;
    if(k&1){
        l=p[1].dis;
        tmp[p[1].dis]++;
        for(register int i=2;i<=k;i++){
            tmp[p[i].dis]++; 
            if(p[i].dis>l) num2++;
            else num1++;
        }
        while(num1<num2) move_right();
        while(num2<num1) move_left();
        ans+=S[l];
        for(register int i=k+1;i<=n;i++){
            tmp[p[i].dis]++;
            if(p[i].dis>l) num2++;
            else num1++;
            tmp[p[i-k].dis]--;
            if(p[i-k].dis==l){
                if(num2) move_right();
                else move_left();
            }
            if(p[i-k].dis>l) num2--; 
            else num1--;
            while(num1<num2) move_right();
            while(num2<num1) move_left();
            ans+=S[l];
        }
    }
    else{
        l=p[1].dis;
        tmp[p[1].dis]++;
        for(register int i=2;i<=k;i++){
            tmp[p[i].dis]++; 
            if(p[i].dis>l) num2++;
            else num1++;
        }
        while(num1<num2-1) move_right();
        while(num2<num1+1) move_left();
        r=l+1;
        while(tmp[r]==0&&r<=n) r++;
        ans=(1.0*(S[l]+S[r]))/2.0;
    //    cout<<(1.0*S[l]+1.0*S[r])/2.0<<endl;
        for(register int i=k+1;i<=n;i++){
            tmp[p[i].dis]++;
            if(p[i].dis>l) num2++;
            else num1++;
            tmp[p[i-k].dis]--;
            if(p[i-k].dis==l){
                if(num2) move_right();
                else move_left();
            }
            if(p[i-k].dis>l) num2--; 
            else num1--;
            while(num1<num2-1) move_right();
            while(num2<num1+1) move_left();
            r=l+1;
            while(tmp[r]==0&&r<=n) r++;
            ans+=((1.0*(S[l]+S[r]))/2.0);
            //cout<<(1.0*S[l]+1.0*S[r])/2.0<<endl;
        }
    }
    printf("%.1lf
",ans);
}
未调完

  Game

    乍一看还以为博弈论,实际就是每个人都拿集合中最大的数,而集合中的最大值不升,如果要进集合的数大于集合最大值,拿走这个数,否则  拿走最大值并把这个数加进集合

    不要用堆维护最大值,因为单调不升,开桶~  

技术图片
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int n,k,tmp[110000],a[110000],b[110000];
long long sum[2];
int main(){
    scanf("%d%d",&n,&k);
    for(register int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
    b[0]=n;
    sort(b+1,b+b[0]+1);
    b[0]=unique(b+1,b+b[0]+1)-b-1;
    for(register int i=1;i<=n;i++){
        a[i]=lower_bound(b+1,b+b[0]+1,a[i])-b;
    }
    int p;
    while(k--){
        scanf("%d",&p);
        int l=0,cur=0;
        for(register int i=1;i<=p;i++) tmp[a[i]]++,l=l>a[i]?l:a[i];
        sum[0]=sum[1]=0;
        sum[0]=b[l];
        tmp[l]--;
        while(tmp[l]==0&&l) l--;
        for(register int i=p+1;i<=n;i++){
            cur^=1;
            if(a[i]>=l)    sum[cur]+=b[a[i]];
            else{
                sum[cur]+=b[l];
                tmp[l]--;
                tmp[a[i]]++;
                while(tmp[l]==0&&l) l--;
            }
        }
        while(l){
            cur^=1;
            sum[cur]+=b[l];
            tmp[l]--;
            while(tmp[l]==0&&l) l--;
        }
        printf("%lld
",sum[0]-sum[1]);
    }
}
View Code

   Park

    树上DP,维护两个三位DP数组,一个表示从子树中走到根,一个表示从根走向子树,撒了多少面包屑,该点撒还是不撒,合并是考虑周全

技术图片
#include<iostream>
#include<cstdio>
using namespace std;
int n,v,to[210000],nex[210000],head[110000],tot;
long long f[110000][110][2],tmp[110000][110][2],sum[110000],c[110000],ans;
void add(int x,int y){
    to[++tot]=y,nex[tot]=head[x],head[x]=tot;
}
void dfs(int x,int pre){
    sum[x]=c[pre];
    for(register int i=head[x];i;i=nex[i]){
        int y=to[i];
        if(y==pre) continue;
        dfs(y,x);
        sum[x]+=c[y];
    }
}
void DFS(int x,int pre){
    f[x][1][1]=sum[x];
    tmp[x][1][1]=sum[x];
    for(register int i=head[x];i;i=nex[i]){
        int y=to[i];
        if(y==pre) continue;
        DFS(y,x);
        for(register int j=0;j<=v;j++){
            ans=max(ans,max(tmp[x][j][0]+max(f[y][v-j][0],f[y][v-j][1]),tmp[x][j][1]+max(f[y][v-j][0],f[y][v-j][1])-c[y]));
            ans=max(ans,max(f[x][j][0]+max(tmp[y][v-j][0],tmp[y][v-j][1]),f[x][j][1]+max(tmp[y][v-j][0],tmp[y][v-j][1])));
        }
        for(register int j=0;j<=v;j++){
            if(j>0){
                f[x][j][0]=max(f[x][j][0],f[x][j-1][0]);
                f[x][j][1]=max(f[x][j][1],f[x][j-1][1]);
                tmp[x][j][0]=max(tmp[x][j][0],tmp[x][j-1][0]);
                tmp[x][j][1]=max(tmp[x][j][1],tmp[x][j-1][1]);
            }
            f[x][j][0]=max(f[x][j][0],max(f[y][j][0],f[y][j][1]));
            if(j>0) f[x][j][1]=max(f[x][j][1],max(f[y][j-1][0],f[y][j-1][1])+sum[x]-c[y]);
            tmp[x][j][0]=max(tmp[x][j][0],max(tmp[y][j][0],tmp[y][j][1]));
            if(j>0) tmp[x][j][1]=max(tmp[x][j][1],max(tmp[y][j-1][1],tmp[y][j-1][0])+sum[x]);
        }
    }
    for(register int i=0;i<=v;i++){
        ans=max(ans,max(f[x][i][1],f[x][i][0]));
        ans=max(ans,max(tmp[x][i][0],tmp[x][i][1]));
        tmp[x][i][1]-=c[pre];
        //printf("x=%d i=%d f[%d][%d][1]=%lld f[%d][%d][0]=%lld tmp[%d][%d][1]=%lld tmp[%d][%d][0]=%lld
",x,i,x,i,f[x][i][1],x,i,f[x][i][0],x,i,tmp[x][i][1],x,i,tmp[x][i][0]);
    }
}
int main(){
    scanf("%d%d",&n,&v);
    for(register int i=1;i<=n;i++) scanf("%lld",&c[i]);
    for(register int i=1,x,y;i<n;i++){
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
    }
    dfs(1,0);
    DFS(1,0);
    printf("%lld",ans);
}
View Code

模拟64

  trade好题

    反悔贪心

技术图片
#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
using namespace std;
int n;
long long ans;
priority_queue<int>q;
int main(){
    scanf("%d",&n);
    for(register int i=1,x;i<=n;i++){
        scanf("%d",&x);
        if(q.empty()||abs(q.top())>x) q.push(-x);
        else{
            ans+=x+q.top();
            q.pop();
            q.push(-x);
            q.push(-x);
        }
    }
    printf("%lld
",ans);
}
View Code

  sum  

    莫队

技术图片
//不要忘了大样例
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int id,Q,bl[110000],blc;
const int mod=1e9+7;
long long fac[110000],inv[110000],ans[110000],cet;
struct node{
    int n,m,id;
    bool operator < (const node b)const{
        return bl[n]==bl[b.n]?(bl[m]<bl[b.m]):(bl[n]<bl[b.n]);
    }
}q[110000];
long long qpow(long long a,long long b){
    long long ans=1;
    while(b){
        if(b&1) ans=ans*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return ans;
}
int main(){
    //freopen("sum3.in","r",stdin);
    //freopen("2.out","w",stdout);
    scanf("%d%d",&id,&Q);
    blc=sqrt(100000);
    fac[0]=1;
    for(register int i=1;i<=100000;i++)
        fac[i]=fac[i-1]*i%mod,bl[i]=(i-1)/blc;
    inv[100000]=qpow(fac[100000],mod-2);
    inv[0]=1;
    for(register int i=99999;i>=1;i--) inv[i]=1ll*inv[i+1]*(i+1)%mod; 
    for(register int i=1;i<=Q;i++) scanf("%d%d",&q[i].n,&q[i].m),q[i].id=i;
    sort(q+1,q+Q+1);
    int n=1,m=0;
    cet=1;
    for(register int i=1;i<=Q;i++){
        while(n<q[i].n) cet=(cet*2%mod-fac[n]*inv[m]%mod*inv[n-m]%mod)%mod,n++;
        while(m<q[i].m) m++,cet=(cet+fac[n]*inv[m]%mod*inv[n-m]%mod)%mod;
        while(m>q[i].m) cet=(cet-fac[n]*inv[m]%mod*inv[n-m]%mod)%mod,m--;
        while(n>q[i].n) n--,cet=(cet+fac[n]*inv[m]%mod*inv[n-m]%mod)%mod*inv[2]%mod;
        ans[q[i].id]=(cet+mod)%mod;
    }
    for(register int i=1;i<=Q;i++) printf("%lld
",ans[i]);
}
View Code

  building

    大模拟

技术图片
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
struct Hang{
    int l,r,id;
    bool operator < (const Hang b)const{
        return (l<b.l)||(l==b.l&&r<b.r);
    }
};
struct Lie{
    int u,d,id;
    bool operator < (const Lie b)const{
        return (u<b.u)||(u==b.u&&d<b.d);
    }
};
struct node{
    int l,r,u,d,id;
    bool operator < (const node b)const{
        return (u<b.u)||(u==b.u&&l<b.l);
    }
}w[110000];
vector<Hang>hang[110000];
vector<Lie>lie[110000];
int id,n,m,k,q,fa[110000];
long long sumh[110000],sum[110000],num[110000];
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
void search_h(Hang Lockey,int i,int e){
    int j=lower_bound(hang[e].begin(),hang[e].end(),Lockey)-hang[e].begin()-1;
    for(;j<hang[e].size();j++){
        if(hang[e][j].r<w[i].l) continue;
        if(hang[e][j].l>w[i].r) break;
        int x=find(w[i].id),y=find(hang[e][j].id);
        if(x!=y){
            num[w[i].u]--;
            fa[x]=y;
        }
    }
}
void search_l(Lie dog,int i,int e){
    int j=lower_bound(lie[e].begin(),lie[e].end(),dog)-lie[e].begin()-1;
    for(;j<lie[e].size();j++){
        if(lie[e][j].d<w[i].u) continue;
        if(lie[e][j].u>w[i].u) break;
        int x=find(w[i].id),y=find(lie[e][j].id);
        if(x!=y){
            num[w[i].u]--;
            fa[x]=y;
        }
    }
}
int main(){
    scanf("%d%d%d%d%d",&id,&n,&m,&k,&q);
    for(register int i=1,u,l,d,r;i<=k;i++){
        scanf("%d%d%d%d",&w[i].u,&w[i].l,&w[i].d,&w[i].r);w[i].id=i,fa[i]=i;
        if(w[i].u==w[i].d){
            sumh[w[i].u]+=w[i].r-w[i].l+1;
            hang[w[i].u].push_back((Hang){w[i].l,w[i].r,i});
            lie[w[i].r].push_back((Lie){w[i].u,w[i].d,i});
        }
        else{
            sum[w[i].u]++,sum[w[i].d+1]--;
            lie[w[i].l].push_back((Lie){w[i].u,w[i].d,i});
            hang[w[i].d].push_back((Hang){w[i].l,w[i].r,i});
        }
    }
    sort(w+1,w+k+1);
    for(register int i=1;i<=max(n,m);i++){
        hang[i].push_back((Hang){-5,-5,0});
        lie[i].push_back((Lie){-5,-5,0});
        sort(hang[i].begin(),hang[i].end());
        sort(lie[i].begin(),lie[i].end());
    }
    for(register int i=1;i<=n;i++)    sum[i]+=sum[i-1];
    for(register int i=1;i<=n;i++)    sum[i]+=sumh[i]+sum[i-1];
    int u,v,e;
    for(register int i=1;i<=k;i++){
        if(w[i].u==w[i].d){
            num[w[i].u]++;
            Hang Lockey=(Hang){w[i].l,w[i].r,0};
            e=w[i].u-1,search_h(Lockey,i,e);
            Lie dog=(Lie){w[i].u,w[i].u,0};
            e=w[i].l-1,search_l(dog,i,e);
            e=w[i].r+1,search_l(dog,i,e);
        }
        else{
            num[w[i].u]++;
            Lie dog=(Lie){w[i].u,w[i].u,0};
            e=w[i].l-1,search_l(dog,i,e);
            e=w[i].r+1,search_l(dog,i,e);
            Hang Lockey=(Hang){w[i].l,w[i].r,0};
            e=w[i].u-1,search_h(Lockey,i,e);
        }
    }
    for(register int i=1;i<=n;i++)    num[i]+=num[i-1];
    while(q--){
        scanf("%d%d",&u,&v);
        if(u==0) printf("%lld
",sum[v]);
        else printf("%lld
",num[v]);
    }
}
View Code

模拟65

  Simple 

    不太会,听他们说跟小凯的疑惑有共通的地方----赛瓦维斯特定理,可以看这个gay的博客

技术图片
#include<iostream>
#include<cstdio>
using namespace std;
int T;
long long n,m;
long long q;
long long gcd(long long a,long long b){return b?gcd(b,a%b):a;}
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%lld%lld%lld",&n,&m,&q);
        long long g=gcd(n,m);
        long long cet=q;
        if(n>m) swap(n,m);
        long long num=0;
        for(register long long i=0;i<n/g;i++){
            if(q-1ll*i*m<0) break;
            num+=((q-i*m)/n)+1;
        }
        printf("%lld
",cet-num+1);
    }
}
View Code

  技术图片

  Walk

    拆边,将一个边拆成边权的因子的多条边,按因子可以将边分成几个集合,然后建树跑DFS求直径,也可以用按秩合并并查集+树剖求LCA+结  构体封装优化+卡常轻(艰)松(难)切掉

技术图片
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
int n,prm[410000],num[110],v[1100000],ans[410000],to[810000],nex[810000],head[410000],tot;
struct BCJ{
    int root,l,r,d,dep,tim;
    void clear(int x){
        root=x,l=x,r=x,d=0,dep=1;
    }
}bcj[410000];
struct curtree{
    int dis,fa,son,size,top;
}tr[410000];
void add(int x,int y){
    to[++tot]=y,nex[tot]=head[x],head[x]=tot;
}
struct node{
    int f,t,w;
}e[410000];
vector<int>vec[1100000];
void search(int d,int ans,int id){
    if(d==prm[0]+1){
        vec[ans].push_back(id);
        return;
    }
    search(d+1,ans,id);
    for(register int i=1;i<=num[d];i++)
        ans*=prm[d],search(d+1,ans,id);
}
void fenjie(int x,int id){
    prm[0]=0;
    while(x!=1){
        prm[++prm[0]]=v[x];
        int w=v[x];
        num[prm[0]]=0;
        while(v[x]==w) x/=v[x],num[prm[0]]++;
    }
    search(1,1,id);
}
void DFS(int x,int pre){
    tr[x].top=bcj[x].root=bcj[x].l=bcj[x].r=x;
    bcj[x].d=bcj[x].dep=0;
    tr[x].size=1;
    tr[x].fa=pre;
    tr[x].dis=tr[pre].dis+1;
    for(register int i=head[x];i;i=nex[i]){
        int y=to[i];
        if(y==pre) continue;
        DFS(y,x);
        tr[x].son=tr[tr[x].son].size>tr[y].size?tr[x].son:y;
        tr[x].size+=tr[y].size;
    }
}
void dfs(int x,int pre){
    if(tr[x].son) tr[tr[x].son].top=tr[x].top,dfs(tr[x].son,x);
    for(register int i=head[x];i;i=nex[i]){
        int y=to[i];
        if(y==pre||y==tr[x].son) continue;
        dfs(y,x);
    }
}
int lca(int x,int y){
    register int xx=tr[x].top,yy=tr[y].top;
    while(xx!=yy){
        if(tr[xx].dis>tr[yy].dis) x=tr[xx].fa,xx=tr[x].top;
        else y=tr[yy].fa,yy=tr[y].top;
    }
    return tr[x].dis<tr[y].dis?x:y;
}
void merge(int x,int y){
    register int u[5];
    u[1]=bcj[x].l,u[2]=bcj[x].r,u[3]=bcj[y].l,u[4]=bcj[y].r;
    if(bcj[x].dep>bcj[y].dep) bcj[x].dep=max(bcj[x].dep,bcj[y].dep+1),bcj[y].root=bcj[x].root;
    else bcj[y].dep=max(bcj[x].dep+1,bcj[y].dep),bcj[x].root=bcj[y].root;
    for(register int i=1;i<=2;i++){
        for(register int j=3;j<=4;j++){
            int len=tr[u[i]].dis+tr[u[j]].dis-2*tr[lca(u[i],u[j])].dis;
            if(len>bcj[bcj[x].root].d){
                bcj[bcj[x].root].l=u[i],bcj[bcj[x].root].r=u[j];
                bcj[bcj[x].root].d=len;
            }
        }
    }
}
int find(register int x){
    while(x!=bcj[x].root) x=bcj[x].root;
    return x;
}
void work(int x){
    for(register int i=0;i<vec[x].size();i++){
        register int u=vec[x][i];
        if(bcj[e[u].f].tim!=x) bcj[e[u].f].clear(e[u].f);
        if(bcj[e[u].t].tim!=x) bcj[e[u].t].clear(e[u].t);
        register int fr=find(e[u].f),tt=find(e[u].t);
        merge(fr,tt);
        bcj[fr].tim=bcj[tt].tim=x;
        ans[bcj[bcj[fr].root].d]=max(ans[bcj[bcj[fr].root].d],x);
    }
}
inline int read(){
    register int ret;
    register char r;
    while(r=getchar(),r<0||r>9);
    ret=r^48;
    while(r=getchar(),r>=0&&r<=9) ret=(ret<<1)+(ret<<3)+(r^48);
    return ret;
}
int main(){
//    freopen("ex_walk2.in","r",stdin);
//    freopen("1.out","w",stdout);
    n=read();
    int maxn=0;
    for(register int i=1;i<n;i++){
        e[i].f=read(),e[i].t=read(),e[i].w=read();
        add(e[i].f,e[i].t);
        add(e[i].t,e[i].f);
        maxn=max(maxn,e[i].w);
    }
    for(register int i=2;i<=maxn;i++){
        if(!v[i]) v[i]=i,prm[++prm[0]]=i;
        for(register int j=1;j<=prm[0]&&i*prm[j]<=maxn;j++){
            v[prm[j]*i]=prm[j];
            if(i%prm[j]==0) break;
        }
    }
    for(register int i=1;i<n;i++) fenjie(e[i].w,i);
    DFS(1,0);
    dfs(1,0);
    for(register int i=1;i<=maxn;i++)
        work(i);
    for(register int i=n;i>=1;i--) ans[i]=max(ans[i],ans[i+1]);
    for(register int i=1;i<=n;i++) printf("%d
",ans[i]);
}
按秩合并并查集+树剖+结构体封装优化+卡常
技术图片
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
int n,prm[410000],num[110],v[1100000],ans[410000],to[24100000],nex[24100000],head[410000],tot,vis[410000];
void add(int x,int y){
    to[++tot]=y,nex[tot]=head[x],head[x]=tot;
}
struct node{
    int f,t,w;
}e[410000];
vector<int>vec[1100000];
void search(int d,int ans,int id){
    if(d==prm[0]+1){
        vec[ans].push_back(id);
        return;
    }
    search(d+1,ans,id);
    for(register int i=1;i<=num[d];i++)
        ans*=prm[d],search(d+1,ans,id);
}
void fenjie(int x,int id){
    prm[0]=0;
    while(x!=1){
        prm[++prm[0]]=v[x];
        int w=v[x];
        num[prm[0]]=0;
        while(v[x]==w) x/=v[x],num[prm[0]]++;
    }
    search(1,1,id);
}
int d;
int dfs(int x,int pre){
    int maxn=0;
    vis[x]=1;
    for(register int i=head[x];i;i=nex[i]){
        int y=to[i];
        if(y==pre) continue;
        int w=dfs(y,x);
        d=max(maxn+w,d);
        maxn=max(maxn,w);
    }
    return maxn+1;
}
void work(int x){
    d=0;
    for(register int i=0;i<vec[x].size();i++){
        int y=vec[x][i];
        add(e[y].f,e[y].t);
        add(e[y].t,e[y].f);
    }
    for(register int i=0;i<vec[x].size();i++){
        int y=vec[x][i];
        if(!vis[e[y].f])
            dfs(e[y].f,0);
    }
    ans[d]=x;
    for(register int i=0;i<vec[x].size();i++){
        int y=vec[x][i];
        head[e[y].f]=head[e[y].t]=0;
        vis[e[y].f]=vis[e[y].t]=0;
    }
    tot=0;
}
int main(){
    scanf("%d",&n);
    for(register int i=2;i<=1000000;i++){
        if(!v[i]) v[i]=i,prm[++prm[0]]=i;
        for(register int j=1;j<=prm[0]&&i*prm[j]<=1000000;j++){
            v[prm[j]*i]=prm[j];
            if(i%prm[j]==0) break;
        }
    }
    for(register int i=1;i<n;i++){
        scanf("%d%d%d",&e[i].f,&e[i].t,&e[i].w);
        fenjie(e[i].w,i);
    }
    for(register int i=1;i<=1000000;i++)
        work(i);
    for(register int i=n;i>=1;i--) ans[i]=max(ans[i],ans[i+1]);
    for(register int i=1;i<=n;i++) printf("%d
",ans[i]);
}
正解

   Travel未填之坑

    贪心+模拟

模拟 66

  棋盘  

    经推(打)导(表) $f[i]=f[i-1]*i+(-1)^{[i&1]}$ 没用高精他挂了 ,正解式子 

        技术图片

技术图片
#include<iostream>
#include<cstdio>
using namespace std;
int n,f[510];
char a[210];
void multi(int x){
    int tmp=0;
    for(register int i=1;i<=f[0];i++){
        tmp=f[i]*x+tmp;
        f[i]=tmp%10;
        tmp/=10;
    }
    while(tmp) f[++f[0]]=tmp%10,tmp/=10;
}
void jian(int x){
    f[1]--;
    for(register int i=1;i<=f[0];i++){
        if(f[i]<0) f[i]+=10,f[i+1]--;
        else break;
    }
    while(f[f[0]]==0) f[0]--;
}
void jia(int x){
    f[1]++;
    for(register int i=1;i<=f[0];i++){
        if(f[i]==10) f[i]=0,f[i+1]++;
        else break;
    }
    f[0]++;
    while(f[f[0]]==0) f[0]--;
}
int main(){
    scanf("%d",&n);
    for(register int i=1;i<=n;i++) scanf("%s",a);
    f[++f[0]]=1;
    for(register int i=3;i<=n;i++){
        multi(i);
        if(i&1) jian(1);
        else jia(1);
    }
    while(f[0]) cout<<f[f[0]],f[0]--;
}
View Code

   传递

    bitset 暴力水过,正解将q分正反向与p建图,判断是否是DAG

技术图片
#include<iostream>
#include<cstdio>
#include<bitset>
using namespace std;
int T,n;
char a[2100];
bitset<2020>P[2100],Q[2100];
int judge(){
    for(register int i=1;i<=n;i++)
        for(register int j=1;j<=n;j++)
            if(P[i][j]==1)
                if((P[i]&P[j])!=P[j]) return 0;
    for(register int i=1;i<=n;i++)
        for(register int j=1;j<=n;j++)
            if(Q[i][j]==1)
                if((Q[i]&Q[j])!=Q[j]) return 0;

    return 1;
}
int main(){
    //freopen("1.in","r",stdin);
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(register int i=1;i<=n;i++){
            scanf("%s",a+1);
            P[i].reset(),Q[i].reset();
            for(register int j=1;j<=n;j++){
                if(a[j]==P) P[i][j]=1;
                else if(a[j]==Q) Q[i][j]=1;
            }
        }
        if(judge()) puts("T");
        else puts("N");
    }
}
bitset暴力水过

  异或神题)(未填

    比数位DP还恶心的数位DP

模拟67

  神炎皇

    因为$ a+b|ab,a=k_1*c,b=k_2*c $所以 $a+b=(k_1+k_2)*cRightarrow ab=k_1k_2c^2 Rightarrow(k_1+k_2)|k_1k_2c $

    又因为 $ gcd(k_1,k_2)=1  Rightarrow  gcd(k_1,k_1k_2)=1,gcd(k_2,k_1k_2)=1 $所以$(k1+k2)|c且gcd(k_1,k_2)=1$

    因为$a+b<=n$所以$c(k_1+k_2)<=n$ ,因为$ c=x*(k_1+k_2)$,所以$x*(k_1+k_2)^2<=n$

    因此枚举$k_1+k_2=S$的S,那么x的个数就是$n/(S^2)$,而(k_1,k_2)的组数就是$ varphi(S) $

    所以只要求 $sumlimits_{s=2}^{sqrt(n)}varphi(s)*n/(s^2) $

技术图片
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
long long n;
int phi[11000000],prm[700000];
int main(){
    scanf("%lld",&n);
    phi[1]=1;
    for(register int i=2;i<=10000000;i++){
        if(!phi[i]) phi[i]=i-1,prm[++prm[0]]=i;
        for(register int j=1;j<=prm[0]&&i*prm[j]<=10000000;j++){
            if(i%prm[j]==0){phi[i*prm[j]]=phi[i]*prm[j];break;}
            else phi[i*prm[j]]=phi[i]*(prm[j]-1);
        }
    }
    long long ans=0;
    for(register int i=2;i<=sqrt(n);i++){
        ans=ans+1ll*phi[i]*(n/(1ll*i*i));
    }
    printf("%lld
",ans);
}
View Code

  降雷皇

    LIS问题,树状数组维护最大值,(注意参数要读全,我AC代码因为没读入type而Wa10)

技术图片
#include<iostream>
#include<cstdio>
using namespace std;
int n,a[110000];
const long long mod=123456789;
struct node{
    int maxn;
    long long num;
}tr[110000];
int lowbit(int x){return x&(-x);}
node ask(int x){
    node ans=(node){0,1};
    while(x){
        if(tr[x].maxn==ans.maxn) (ans.num+=tr[x].num)%=mod;
        else if(tr[x].maxn>ans.maxn) ans=tr[x];
        x-=lowbit(x);
    }
    return ans;
}
void add(int x,node w){
    while(x<=100000){
        if(tr[x].maxn==w.maxn) (tr[x].num+=w.num)%=mod;
        else if(w.maxn>tr[x].maxn)tr[x]=w;
        x+=lowbit(x);
    }
}
int main(){
    int shabi;
    scanf("%d%d",&n,&shabi);
    for(register int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(register int i=1;i<=n;i++){
        node w=ask(a[i]-1);
        w.maxn++;
        add(a[i],w);
    }
    node ans=ask(100000);
    if(shabi) printf("%d
%lld
",ans.maxn,ans.num);
    else printf("%d
",ans.maxn);
}
View Code

  幻魔皇 好题

    懒得写了,还是那个gay的幻魔皇题解

技术图片
#include<iostream>
#include<cstdio>
using namespace std;
int n;
long long sumW[5100],sumB[5100],f[5100],g[5100],ans[11000];
const int mod=123456789;
int main(){
    scanf("%d",&n);
    sumW[1]=sumB[2]=f[0]=1;
    for(register int i=3;i<=n;i++)
        sumW[i]=(sumW[i-1]+sumW[i-2])%mod,
        sumB[i]=(sumB[i-1]+sumB[i-2])%mod;
    for(register int i=1;i<=n;i++)
        sumW[i]=(sumW[i]+sumW[i-1])%mod,
        sumB[i]=(sumB[i]+sumB[i-1])%mod;
    for(register int i=1;i<=n;i++)
        g[i]=(g[i-1]+f[i-1])%mod,f[i]=g[i-1];
    for(register int i=1;i<=n;i++) ans[i]=(ans[i]+f[i]*sumW[n-i]%mod)%mod;
    for(register int i=1;i<=n;i++)
        for(register int j=1;j<=n;j++)
            ans[i+j]=(ans[i+j]+f[i-1]*g[j-1]%mod*sumB[n-max(i,j)]%mod)%mod;
    for(register int i=1;i<=2*n;i++) printf("%lld ",ans[i]%mod);
}
View Code

模拟68

  d 

    肯定是删够m个才有最大的交集,枚举删i个a最小的,那么删去m-i个b最小的,a用sort排序,b放堆里面

技术图片
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
int T,n,m,v[110000];
struct node{
    int id,a,b;
    bool operator < (const node x)const{
        return a<x.a;
    }
}w[110000];
struct Node{
    int id,a,b;
    bool operator < (const Node x)const{
        return (b>x.b)||(b==x.b&&a>x.a);
    }
};
priority_queue<Node>q;
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        for(register int i=1;i<=n;i++){
            scanf("%d%d",&w[i].a,&w[i].b),w[i].id=i;
        }
        sort(w+1,w+n+1);
        long long ans=0,minna=w[m+1].a;
        for(register int i=m+1;i<=n;i++) q.push((Node){w[i].id,w[i].a,w[i].b});
        for(register int i=m;i>=0;i--){
            ans=max(ans,minna*q.top().b);
            if(w[i].b>=q.top().b) minna=min(minna,1ll*w[i].a),q.pop(),q.push((Node){w[i].id,w[i].a,w[i].b});
        }
        while(q.size())q.pop();
        printf("%lld
",ans);
    }
}
View Code

  e 好题

    树上主席树或主席树上树(^_^)维护一个点到根的那条链上的点权,所要查的联通块其实就是所有pi 到他们lca 的链的并

    用pi的主席树减lca的父亲的主席树,查询r的前驱和后继

技术图片
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int n,q,type,a[110000],fa[110000][19],dis[110000];
int to[210000],nex[210000],head[110000],tot;
int root[110000],ls[8100000],rs[8100000],num[8100000],cet;
int p[110000];
const int upw=1e9;
void add(int x,int y){
    to[++tot]=y,nex[tot]=head[x],head[x]=tot;
}
void add_point(int &t1,int t2,int l,int r,int x){
    if(!t1) t1=++cet;
    if(l==r){
        num[t1]=num[t2]+1;
        return;
    }
    int mid=(l+r)>>1;
    if(mid>=x){
        add_point(ls[t1],ls[t2],l,mid,x);
        rs[t1]=rs[t2];
    }
    else{
        add_point(rs[t1],rs[t2],mid+1,r,x);
        ls[t1]=ls[t2];
    }
    num[t1]=num[ls[t1]]+num[rs[t1]];
}
int ask_max(int t1,int t2,int l,int r,int L,int R){
    if(num[t1]==num[t2]) return 0;
    if(l==r) return l; 
    int mid=(l+r)>>1,ans=0;
    if(mid<R) ans=ask_max(rs[t1],rs[t2],mid+1,r,L,R);
    if(ans) return ans;
    if(mid>=L) ans=ask_max(ls[t1],ls[t2],l,mid,L,R);
    if(ans) return ans;
    return 0;
}
int ask_min(int t1,int t2,int l,int r,int L,int R){
    if(num[t1]==num[t2]) return 0;
    if(l==r) return l; 
    int mid=(l+r)>>1,ans=0;
    if(mid>=L) ans=ask_min(ls[t1],ls[t2],l,mid,L,R);
    if(ans) return ans;
    if(mid<R) ans=ask_min(rs[t1],rs[t2],mid+1,r,L,R);
    if(ans) return ans;
    return 0;
}
void dfs(int x,int pre){
    fa[x][0]=pre;
    dis[x]=dis[pre]+1;
    add_point(root[x],root[pre],1,upw,a[x]);
    for(register int i=1;i<=18;i++) fa[x][i]=fa[fa[x][i-1]][i-1];
    for(register int i=head[x];i;i=nex[i]){
        int y=to[i];
        if(y==pre) continue;
        dfs(y,x);
    }
}
int lca(int x,int y){
    if(x==0) return y;
    if(dis[x]>dis[y]) swap(x,y);
    int i=0;
    for(;(1<<i)<=dis[y];i++);
    for(register int j=i;j>=0;j--)
        if(dis[fa[y][j]]>=dis[x])
            y=fa[y][j];
    if(x==y) return x;
    for(register int j=i;j>=0;j--)
        if(fa[y][j]!=fa[x][j])
            y=fa[y][j],
            x=fa[x][j];
    return fa[x][0];
}
int main(){
    scanf("%d%d%d",&n,&q,&type);
    for(register int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(register int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x);
    dfs(1,0);
    long long r,k,las=0;
    while(q--){
        scanf("%lld%lld",&r,&k);
        int lc=0;
        las%=n;
        for(register int i=1;i<=k;i++){
            scanf("%d",&p[i]);
            p[i]=(p[i]-1+1ll*las*type%n)%n+1;
            lc=lca(lc,p[i]);
        }
        las=0x7ffffffffffff;
        for(register int i=1;i<=k;i++){
            int w1=ask_max(root[p[i]],root[fa[lc][0]],1,upw,1,r);
            int w2=ask_min(root[p[i]],root[fa[lc][0]],1,upw,r,upw);
            if(w1&&w2) las=min(las,min(1ll*r-w1,1ll*w2-r));
            else if(w2) las=min(las,1ll*w2-r);
            else las=min(las,1ll*r-w1);
        }
        printf("%lld
",las);
    }
}
View Code

 

  f神题)(未填

    前i-1高位相同,第i为不同,那么这两个数的大小关系取决于res的第i位,即每一位i的贡献之间没有影响

    01trie树求每一位是0或1的贡献,可以暴力算出每一个res的贡献排序,这样可以拿到55分

    正解是二分f[res],求出有p-1个f值小于f[res],即满足f[res]是第p小

    然后求出最小的res

技术图片
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,k,p;
int num[30000000],to[30000000][2],tot=1,t[31000000];
long long sum[35][2];
struct node{
    int id;
    long long sum;
    bool operator < (const node b)const{
        return (sum<b.sum)||(sum==b.sum&&id<b.id);
    }
}w[50000000];
void add(int x){
    int root=1,c[35];
    for(register int i=0;i<k;i++,x>>=1) c[i]=x&1;
    for(register int i=k-1;i>=0;i--){
        if(to[root][c[i]]==0) to[root][c[i]]=++tot;
        sum[i][c[i]]+=num[to[root][c[i]^1]];
        root=to[root][c[i]];
        num[root]++;
    } 
}
int main(){
    scanf("%d%d%d",&n,&k,&p);
    for(register int i=1,x;i<=n;i++){
        scanf("%d",&x);
        add(x);
    }
    long long cet=0;
    for(register int i=0;i<k;i++){
        t[1<<i]=i;
        sum[i][1]=sum[i][1]-sum[i][0],cet+=sum[i][0];
    }
    w[0].id=0,w[0].sum=cet;
    for(register int i=1;i<(1<<k);i++){
        w[i].sum=w[i^(i&(-i))].sum+sum[t[i&(-i)]][1];
        w[i].id=i;
    }
    nth_element(w+0,w+p-1,w+(1<<k));
    printf("%lld %d
",w[p-1].sum,w[p-1].id);
}
55分暴力

模拟69

  chess

    $O(n^4log)$DP,预处理转移系数,去掉log

技术图片
#include<iostream>
#include<cstdio>
using namespace std;
int n,num;
long long f[110][11000],C[110][110],dp[110][11000];
long long fac[11000];
long long m;
const int mod=1e9+7;
long long qpow(long long a,long long b){
    long long ans=1;
    while(b){
        if(b&1) ans=ans*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return ans%mod;
}
int main(){
    scanf("%d%lld%d",&n,&m,&num);
    if(m==n){
        fac[0]=1;
        for(register int i=1;i<=n*n;i++) fac[i]=fac[i-1]*i%mod;
        printf("%lld
",fac[n*n]*qpow(fac[num]*fac[n*n-num]%mod,mod-2)%mod);
        return 0;
    }
    for(register int i=0;i<=n;i++){
        C[i][0]=1;
        for(register int j=1;j<=i;j++) C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
    }
    if(num>n*n/2) num=n*n-num;
    for(register int i=1;i<=n;i++){
        long long tim=m/n;
        if(m%n>=i) tim++;
        tim%=(mod-1);
        for(register int j=0;j<=num;j++){
            dp[i][j]=qpow(C[n][j],tim);
        }
    }
    f[0][0]=1;
    for(register int i=1;i<=n;i++){
        for(register int j=0;j<=num;j++){
            for(register int k=0;k<=j;k++){
                f[i][j]=(f[i][j]+f[i-1][k]*dp[i][j-k]%mod)%mod;
            }
        }
    }
    printf("%lld
",f[n][num]);
}
所谓n^5,实际特判A掉的代码

  array好题

    单调栈维护单调不下降序列,如果当前走到i且弹完栈插入i,那么栈中元素k到i之间没有比a[k]更小的元素,所以只需要找k到i之间最大的  元素的位置s,来用s-k+1更新答案

    可以用一个数组maxn[k]记录k到当前点之间最大的元素的位置,显然栈顶的maxn可以更新栈内的所有元素的maxn,(top出栈的时候,和下  一个取max传下去即可)

    所以是$O(1)$更新,总复杂度$O(n)$

技术图片
#include<iostream>
#include<cstdio>
using namespace std;
int n,a[11000000],st[11000000],maxn[11000000];
inline int read(){
    register int ret;
    register char r;
    while(r=getchar(),r<0||r>9);
    ret=r^48;
    while(r=getchar(),r>=0&&r<=9) ret=(ret<<1)+(ret<<3)+(r^48);
    return ret;
}
int main(){
    //freopen("2.in","r",stdin);
    //freopen("2.out","w",stdout);
    n=read();
    for(register int i=1;i<=n;i++) a[i]=read();
    int ans=0;
    for(register int i=1;i<=n+1;i++){
        while(st[0]&&a[st[st[0]]]>a[i]){
            if(a[maxn[st[0]-1]]<=a[maxn[st[0]]]) maxn[st[0]-1]=maxn[st[0]];
            ans=max(ans,maxn[st[0]]-st[st[0]]+1);
            maxn[st[0]]=0;
            st[0]--;
        }
        if(i==n+1) break;
        st[++st[0]]=i;
        maxn[st[0]]=i;
    }
    printf("%d
",ans);
}
View Code

  ants好题

    莫队+线段树,但是会TLE50

    可以用回滚莫队+链表思想

    这里用到了一个更强大的莫队——回滚莫队:

      如果待查区间在同一个块或在两个相邻的块,暴力扫,

      如果待查区间在不同的块(块不相邻)里,将整块暴力扫进去,然后在这基础上向左向右扩展不到一个块的部分,统计完答案后delet恢    复原来的基础状态(整块的状态)

      特殊的,我们把块编号[1,n],对于当前基础状态包含块[l,r-1],而当前整块有[l,r],那么在原状态的基础上加上r 这个块的贡献,并    把块[l,r]的贡献作为新的基础状态

      非常优雅

技术图片
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int n,m,blc,bl[110000],a[110000],ans[110000];
int L[110000],R[110000],st[110000],top,upw,cet;
struct node{
    int l,r,id;
    char operator < (const node b)const{
        return bl[l]==bl[b.l]?(r<b.r):(bl[l]<bl[b.l]);
    }
}q[110000];
inline int read(){
    register int ret;
    register char r;
    while(r=getchar(),r<0||r>9);
    ret=r^48;
    while(r=getchar(),r>=0&&r<=9) ret=(ret<<1)+(ret<<3)+(r^48);
    return ret;
}
void add(int x){
    L[x]=R[x]=x;
    if(L[x-1]) L[x]=min(L[x],L[x-1]);
    if(R[x+1]) R[x]=max(R[x],R[x+1]);
    if(L[x-1]) R[L[x-1]]=R[x];
    if(R[x+1]) L[R[x+1]]=L[x];
    st[++top]=x;
    cet=max(cet,R[x]-L[x]+1);
}
void del(){
    while(top>upw){
        int x=st[top--];
        if(L[x]==x&&R[x]==x) L[x]=R[x]=0;
        else if(L[x]==x){
            L[R[x]]=x+1;
            R[x+1]=R[x];
            L[x]=R[x]=0;
        }
        else if(R[x]==x){
            R[L[x]]=x-1;
            L[x-1]=L[x];
            L[x]=R[x]=0;
        }
        else{
            L[R[x]]=x+1;
            R[L[x]]=x-1;
            L[x-1]=L[x];
            R[x+1]=R[x];
            L[x]=R[x]=0;
        }
    }
}
int main(){
    //freopen("1.in","r",stdin);
    //freopen("1.out","w",stdout);
    n=read(),m=read();
    blc=sqrt(n);
    for(register int i=1;i<=n;i++) a[i]=read(),bl[i]=(i-1)/blc+1;
    for(register int i=1;i<=m;i++) q[i].l=read(),q[i].r=read(),q[i].id=i;
    sort(q+1,q+m+1);
    int l=0,r=0;
    for(register int i=1;i<=m;i++){
        if(bl[q[i].r]-bl[q[i].l]<=1){
            cet=upw=0;
            del();
            for(register int j=q[i].l;j<=q[i].r;j++)
                add(a[j]);
            ans[q[i].id]=cet;
            del();
            l=r=0;
        }
        else{
            if(l!=bl[q[i].l]*blc){
                upw=cet=0;
                del();
                r=l=bl[q[i].l]*blc,add(a[l]); 
            }
            while(r<(bl[q[i].r]-1)*blc) ++r,add(a[r]);
            upw=top;
            int las=cet;
            while(l>q[i].l) --l,add(a[l]);
            while(r<q[i].r) ++r,add(a[r]);
            ans[q[i].id]=cet;
            cet=las;
            del();
            l=bl[q[i].l]*blc,r=(bl[q[i].r]-1)*blc;
        }
    }
    for(register int i=1;i<=m;i++) printf("%d
",ans[i]);
}
View Code

 

总结:

    好几天没写博客,一下子全整完真的挺累的。

     不过发现其实时不时的回头看看做过的题也挺好,收获也蛮多的。

     还有30多天就要CSP-S了,希望我能多进步一点儿,但愿能留下来吧。

 

以上是关于CSP-S模拟题(补几天的坑,62~69)的主要内容,如果未能解决你的问题,请参考以下文章

[CSP-S模拟测试69]题解

csp-s模拟测试69

[考试反思]1011csp-s模拟测试69:无常

1002CSP-S模拟测试赛后总结

csp-s模拟测试50(9.22)「施工(单调栈优化DP)」·「蔬菜(二维莫队???)」·「联盟(树上直径)」

csp-s模拟测试50