NOI模拟17

T1 卡片

似乎是个签到题,letitdown一眼切了,我看了好久才看出来这个性质

于是这个启发我们在做题的时候要观察小细节,不要站在高出思考,认真分析每一步的决策变化

AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
    while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
    return s*t;
}
const int N=6e5+5;
int n,m,ans,a[N],b[N],t[N];
int lsh[N],lh;
struct XDS{
    #define ls x<<1
    #define rs x<<1|1
    int mx[N*4];
    void pushup(int x){
        mx[x]=max(mx[ls],mx[rs]);
    }
    void ins(int x,int l,int r,int pos,int v){
        if(l==r)return mx[x]=v,void();
        int mid=l+r>>1;
        if(pos<=mid)ins(ls,l,mid,pos,v);
        else ins(rs,mid+1,r,pos,v);
        pushup(x);
    }
    int qry(int x,int l,int r,int ql,int qr){
        if(ql>qr)return 0;
        if(ql<=l&&r<=qr)return mx[x];
        int mid=l+r>>1,ret=0;
        if(ql<=mid)ret=max(ret,qry(ls,l,mid,ql,qr));
        if(qr>mid)ret=max(ret,qry(rs,mid+1,r,ql,qr));
        return ret;
    }
    #undef ls
    #undef rs
}xds;
struct ZXS{
    struct POT{int ls,rs,sz;}tr[N*20];
    int seg;
    void pushup(int x){
        tr[x].sz=tr[tr[x].ls].sz+tr[tr[x].rs].sz;
    }
    void ins(int &x,int y,int l,int r,int pos){
        x=++seg;tr[x]=tr[y];
        if(l==r)return tr[x].sz++,void();
        int mid=l+r>>1;
        if(pos<=mid)ins(tr[x].ls,tr[y].ls,l,mid,pos);
        else ins(tr[x].rs,tr[y].rs,mid+1,r,pos);
        pushup(x);
    }
    int qry(int x,int y,int l,int r,int ql,int qr){
        if(ql>qr)return 0;
        if(ql<=l&&r<=qr)return tr[y].sz-tr[x].sz;
        int mid=l+r>>1,ret=0;
        if(ql<=mid)ret+=qry(tr[x].ls,tr[y].ls,l,mid,ql,qr);
        if(qr>mid)ret+=qry(tr[x].rs,tr[y].rs,mid+1,r,ql,qr);
        return ret;
    }
}zxs;int rt[N];
signed main(){
    freopen("card.in","r",stdin);
    freopen("card.out","w",stdout);
    n=read();m=read();
    fo(i,1,n){
        lsh[++lh]=a[i]=read();
        lsh[++lh]=b[i]=read();
    }
    fo(i,1,m)lsh[++lh]=t[i]=read();
    sort(lsh+1,lsh+lh+1);
    lh=unique(lsh+1,lsh+lh+1)-lsh-1;
    fo(i,1,n){
        a[i]=lower_bound(lsh+1,lsh+lh+1,a[i])-lsh;
        b[i]=lower_bound(lsh+1,lsh+lh+1,b[i])-lsh;
    }
    fo(i,1,m)t[i]=lower_bound(lsh+1,lsh+lh+1,t[i])-lsh;
    fo(i,1,m){
        xds.ins(1,1,lh,t[i],i);
        zxs.ins(rt[i],rt[i-1],1,lh,t[i]);
    }
    fo(i,1,n){
        int l=a[i],r=b[i];
        if(l>r)swap(l,r);
        int ps=xds.qry(1,1,lh,l,r-1);
        // cerr<<ps<<" "<<zxs.qry(rt[ps],rt[m],1,lh,r,lh)<<endl;
        if(zxs.qry(rt[ps],rt[m],1,lh,r,lh)&1){
            if(ps)ans+=lsh[l];
            else ans+=lsh[b[i]];
        }
        else {
            if(ps)ans+=lsh[r];
            else ans+=lsh[a[i]];
        }
        // cerr<<ans<<endl;
    }
    printf("%lld\n",ans);
    return 0;
}

T2 菜

看错题了....

数位dp,可以说是个传统套路了,我们要求前n-1个数的和大于第n个数

于是我们拆成每一位二进制考虑,转移就行了,如果你要枚举\(2^n\)的话,就T飞了

于是我们按照插头dp的样子一个一个转移就行了,状态中再加两维就好了

代码没有写,Yubai写了

T3 字符串

括号匹配,不知道是第几次做到这样的题了,这个是分治...

首先一个结论,如果是合法的那么我每次消去任意相邻的数一定可以消完

所以我们可以瞎几把合并,并且从两侧出发到某个点合并,如果可以合并那么一定是回文的!

AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ull unsigned long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
    while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
    return s*t;
}
const int N=1e5+5;
const ull bas=131;
ull ba[N],cnt;
struct STA{
    int sta[N],top,zhs[N],fhs[N];
    STA(){top=0;zhs[0]=fhs[0]=0;}
    void init(){top=0;zhs[0]=fhs[0]=0;}
    void ins(int c){
        if(top&&sta[top]==c)top--;
        else {
            sta[++top]=c;
            zhs[top]=zhs[top-1]*bas+c;
            fhs[top]=fhs[top-1]+ba[top-1]*c;
        }
    }
    void ers(int c){
        if(top&&sta[top]==c)top--;
        else {
            sta[++top]=c;
            zhs[top]=zhs[top-1]*bas+c;
            fhs[top]=fhs[top-1]+ba[top-1]*c;
        }
    }
    int operator + (STA a)const{
        int l=0,r=min(top,a.top),mid;
        while(l<r){
            mid=l+r+1>>1;
            if(zhs[top]-zhs[top-mid]*ba[mid]==a.zhs[a.top]-a.zhs[a.top-mid]*ba[mid])l=mid;
            else r=mid-1;
        }
        return zhs[top-l]*ba[a.top-l]+a.fhs[a.top-l];
    }
}ls,rs,tp;
unordered_map<ull,int> mp[4];
int n,a[N],ans;char s[N];
void sol(int l,int r){
    if(l==r)return ;
    int mid=l+r>>1;
    fu(i,r,mid+1)rs.ins(a[i]);sol(l,mid);fo(i,mid+1,r)rs.ers(a[i]);
    fo(i,l,mid)ls.ins(a[i]);sol(mid+1,r);fu(i,mid,l)ls.ers(a[i]);
    // cerr<<l<<" "<<r<<" "<<1.0*clock()/CLOCKS_PER_SEC<<endl;
    tp.init();fo(i,1,3)mp[i].clear();
    fo(i,l,mid)ls.ins(a[i]);
    fu(i,mid,l){
        ls.ers(a[i]);
        fo(j,1,3)if(j!=a[i]){
            ls.ins(j);
            int l=0,r=min(ls.top,tp.top),mid;
            while(l<r){
                mid=l+r+1>>1;
                if(ls.zhs[ls.top]-ls.zhs[ls.top-mid]*ba[mid]==tp.zhs[tp.top]-tp.zhs[tp.top-mid]*ba[mid])l=mid;
                else r=mid-1;
            }
            ull hs=ls.zhs[ls.top-l]*ba[tp.top-l]+tp.fhs[tp.top-l];
            mp[j][hs]++;ls.ers(j);
        }
        tp.ins(a[i]);
    }
    // cerr<<1.0*clock()/CLOCKS_PER_SEC<<endl;
    tp.init();
    fu(i,r,mid+1)rs.ins(a[i]);
    fo(i,mid+1,r){
        rs.ers(a[i]);
        fo(j,1,3)if(j!=a[i]){
            rs.ins(j);
            int l=0,r=min(rs.top,tp.top),mid;
            while(l<r){
                mid=l+r+1>>1;
                if(rs.zhs[rs.top]-rs.zhs[rs.top-mid]*ba[mid]==tp.zhs[tp.top]-tp.zhs[tp.top-mid]*ba[mid])l=mid;
                else r=mid-1;
            }
            ull hs=rs.zhs[rs.top-l]*ba[tp.top-l]+tp.fhs[tp.top-l];
            ans+=mp[a[i]][hs];rs.ers(j);}
        tp.ins(a[i]);
    }
    // cerr<<1.0*clock()/CLOCKS_PER_SEC<<endl;
    // cerr<<l<<" "<<r<<endl;
}
signed main(){
    freopen("string.in","r",stdin);
    freopen("string.out","w",stdout);
    scanf("%s",s+1);n=strlen(s+1);
    ba[0]=1;fo(i,1,n)ba[i]=ba[i-1]*bas;
    fo(i,1,n)a[i]=s[i]-'a'+1;
    sol(1,n);printf("%lld\n",ans);
}

不要写加法啊,传参慢死哦

posted @ 2022-06-08 14:39  fengwu2005  阅读(27)  评论(0编辑  收藏  举报