ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【考试总结】2022-03-29

2022-03-30 12:33:28  阅读:154  来源: 互联网

标签:03 return cur int sum 29 pos 2022 mx


交通

倒序预处理 到达每个路口的时间为绿灯第 \(0\) 秒时到终点的最短用时

转移就是找到后缀第一个区间和在模意义下属于 \([g,g+r)\) 的位置,这个部分可以使用动态开点线段树维护

查询和预处理的需求形式类似,不过查询时直接暴力跑过去了是怎么回事呢

Code Display
const int N=5e4+10;
int f[N],n,g,r,d[N],Q,cyc,s[N];
const int M=N*90;
struct Seg{
    int Mn[M],ls[M],rs[M],tot,rt;
    inline void upd(int pos,int v,int &p,int l=0,int r=g+r-1){
        if(!p) p=++tot;
        if(l==r) return Mn[p]=v,void(); 
        int mid=(l+r)>>1;
        if(pos<=mid) upd(pos,v,ls[p],l,mid);
        else upd(pos,v,rs[p],mid+1,r);
        Mn[p]=n+2;
        if(ls[p]) ckmin(Mn[p],Mn[ls[p]]);
        if(rs[p]) ckmin(Mn[p],Mn[rs[p]]);
        return ;
    }
    inline int query(int st,int ed,int p,int l=0,int r=g+r-1){
        if(!p) return n+2;
        if(st<=l&&r<=ed) return Mn[p];
        int mid=(l+r)>>1,res=n+2;
        if(st<=mid) ckmin(res,query(st,ed,ls[p],l,mid));
        if(ed>mid) ckmin(res,query(st,ed,rs[p],mid+1,r));
        return res;
    }
}T;
inline int ask(int L,int R){
    L%=(g+r); R%=(g+r);
    if(L<=R) return T.query(L,R,T.rt);
    return min(T.query(L,g+r-1,T.rt),T.query(0,R,T.rt));
}
signed main(){
    freopen("traffic.in","r",stdin); freopen("traffic.out","w",stdout);
    n=read(); g=read(); r=read();
    rep(i,1,n+1) d[i]=read(),cyc+=d[i]/(g+r),d[i]%=g+r;
    
    s[1]=d[1];
    for(int i=2;i<=n+1;++i) s[i]=d[i]+s[i-1];
    
    f[n+1]=d[n+1];
    T.upd(s[n]%(g+r),n+1,T.rt);
    
    for(int i=n;i>=1;--i){
        int j=ask(s[i-1]+g,s[i-1]+g+r-1);
        if(j!=n+2){
            int v=s[j-1]-s[i-1];
            f[i]=v+f[j]+(g+r)-v%(g+r);
        }else f[i]=s[n+1]-s[i-1];
        T.upd(s[i-1]%(g+r),i,T.rt);
    }
    int Q=read();
    while(Q--){
        int t=d[1]+read();
        for(int i=2;i<=n+1;++i){
            if(t%(g+r)>=g){
                t+=(g+r)-t%(g+r);
                t+=f[i];
                break;
            }
            t+=d[i];
        }
        print(t+cyc*(g+r)); 
    }
    return 0;
}

选拔

诈 骗 大 师

考虑对于每个询问分开处理:设 \(f_{x,j}\) 表示从 \(x\) 子树里面是否存在一个点的根链满足对应字符串是 \(Q[1..i]\),\(g_{x,j}\) 表示匹配后缀

转移显然可以使用 std::bitset 优化

对于所有询问可以统一处理,将字符串连到一起并添加特殊字符即可

一种可能的实现是记录每个字符在全部字符串中的出现位置,并将特殊字符设为 \('z'+1\),每个树上节点初始化 \(\rm bitset\) 时置为特殊字符对应的出现位置

同时全局维护一个长度为拼接串串长的 \(\rm bitset\),其对应字符串上字符的位置表示用上述前后缀的 \(\rm DP\) 值是否可以 \(\rm and\) 得到

Code Display
const int N=3e4+10;
bitset<N*2> f[N],g[N],ans,b[27];
string s,t[N];
int n,Q;
vector<pair<int,int> > G[N];
int tim,ord[N],fa[N];
inline void get_fa(int x,int fat){
    ord[++tim]=x; fa[x]=fat;
    f[x]=g[x]=b[26];
    for(auto t:G[x]) if(t.fir!=fat) get_fa(t.fir,x);
    return ;
}
signed main(){
    freopen("selection.in","r",stdin); freopen("selection.out","w",stdout);
    n=read();
    for(int i=1;i<n;++i){
        int u=read(),v=read(),k=Getalpha()-'a';
        G[u].emplace_back(v,k);
        G[v].emplace_back(u,k);
    }
    Q=read();
    for(int i=1;i<=Q;++i){
        cin>>t[i];
        s=s+char('z'+1)+t[i];
    }
    s+=char('z'+1);
    int len=s.length();
    for(int i=0;i<len;++i) b[s[i]-'a'][i]=1;
    get_fa(1,0);
    for(int id=n;id>=1;--id){
        int x=ord[id];
        for(auto e:G[x]){
            int t=e.fir; if(t==fa[x]) continue;
            f[t]=(f[t]<<1)&b[e.sec];
            g[t]=(g[t]>>1)&b[e.sec];
            ans=ans|((f[x]<<1)&g[t]);
            ans=ans|(g[x]&(f[t]<<1));
            f[x]|=f[t]; g[x]|=g[t];
        }
    }
    int cur=1;
    for(int i=1;i<=Q;++i){
        int tlen=t[i].size();
        for(int j=0;j<=tlen;++j) if(ans[cur+j]){puts("YES"); goto Succ;}
        puts("NO");
        Succ:;
        cur+=tlen+1;
    }
    return 0;
}

等待

尝试判断某个数字 \(x\) 是否能作为合法的 \(\sum b\),简记 \(a_1\ge a_2\dots\ge a_n\):

  • 如果 \(x\) 的最高位比 \(a_{\max}\) 的最高位高那么删掉 \(a_{\max}\) 变成子问题

  • 如果 \(x\) 的最高位和 \(a_{\max}\) 的最高位相同那么删掉 \(a_{\max}\) 的最高位得到新的 \(\{a\}\) 变成子问题

  • 如果 \(x\) 的最高位比 \(a_{\max}\) 的最高位低那么不合法

不难发现这个做法没有后效性

显然可以在判定低位时保留高位对 \(a\) 的删除作用

具体实现可以使用 \(\text{radix sort}\) 来找到删掉若干个 \(1\) 之后的 \(a_{\max}\),基数排序过程就是维护前 \(i-1\) 位的排序结果并添加第 \(i\) 位,这位不同的直接由这位来决定大小关系

根据需求:对于最高位 \(<i\) 的数字不在处理第 \(i\) 位时考虑

这部分复杂度是 \(\Theta(\sum L)\) 的,懒得对 \(0/1\) 归并可以直接 std::sort,问题不大

发现有些部分可以合并处理,也就是有一段 \(\sum b\) 上的连续位必须同时填 \(1\) ,考虑如下局面:

现在考虑到 \(\sum b\) 的第 \(p\) 位,仍然设 \(a_1\ge a_2\dots\ge a_n\),同时记 \(t_i\) 表示 \(a_i\) 的最高位,记 \(k=\min\{\arg \max\{i+t_i\}\}\)

如果 \(p>k+t_k\) 那么一定有解,因为每个数字都要比其最高位更高的 \(1\) 抵消之,同理若 \(p<k+t_k\) 那么一定没有解,据此可以加速判断

但是仍然有一个 \(p=k+t_k\) 的 \(\text{case}\) 需要处理,那么 \(p\leftarrow p-k,\) 并将 \(a_1\dots a_{k-1}\) 均置零并删掉 \(a_k\) 最高位并递归实现判定

递归次数是 \(\Theta(\sum L)\) 的,置零操作并不需要真的置零,只是需要查询的 \(\max\{i+t_i\}\) 的区间发生了变化而已

使用线段树维护 \(i+t_i\) 的最大值以及最靠左的出现位置,实现上有一个技巧是把 \(i+t_i\) 中的 \(i\) 拆成每个合法叶子上 \(1\) 的累加

Code Display
const int N=6e5+10;
int ones,mxl,n,len[N];
int head[N],nxt[N],id[N],tmp[N];
char ans[N];
string s[N];
bool vis[N];
struct node{
    int mx,sum,pos; node(){mx=sum=pos=0;}
    node(int a,int b,int c){mx=a; sum=b; pos=c;}
    node operator +(const node &a)const{
        node t; t.sum=sum+a.sum;
        if(mx>=sum+a.mx) t.mx=mx,t.pos=pos;
        else t.mx=sum+a.mx,t.pos=a.pos;
        return t;
    }
}t[N<<2];
#define ls p<<1
#define rs p<<1|1
#define lson p<<1,l,mid
#define rson p<<1|1,mid+1,r
inline void push_up(int p){ t[p]=t[ls]+t[rs];}
inline void build(int p,int l,int r){
    if(l==r){
        if(vis[l]) t[p]=node(len[l]+1,1,l);
        return ;
    } int mid=(l+r)>>1;
    build(lson); build(rson);
    return push_up(p);
}
inline void flip(int pos,int p=1,int l=1,int r=ones){
    if(l==r){
        if((vis[l]^=1)) t[p]=node(len[l]+1,1,l);
        else t[p]=t[0];
        return ;
    }
    int mid=(l+r)>>1;
    if(pos<=mid) flip(pos,lson); else flip(pos,rson);
    return push_up(p);
}
inline node query(int st,int ed,int p=1,int l=1,int r=ones){
    if(st<=l&&r<=ed) return t[p];
    int mid=(l+r)>>1; node ret=t[0];
    if(st<=mid) ret=ret+query(st,ed,lson);
    if(ed>mid) ret=ret+query(st,ed,rson);
    return ret;
}
inline bool solve(int l,int h){
    if(l>ones) return 1;
    node cur=query(l,ones);
    if(!cur.sum) return 1;
    // All zero
    if(cur.mx>h) return 0;
    // highest bit illegal
    if(nxt[cur.pos]) flip(nxt[cur.pos]);
    bool legal=solve(cur.pos+1,len[cur.pos]);
    if(nxt[cur.pos]) flip(nxt[cur.pos]);
    if(legal){
        for(int i=len[cur.pos];i<cur.mx;++i) ans[i+1]='1';
        return 1;  
    }
    if(cur.mx>=h) return 0;
    //delete the highest number
    solve(cur.pos+1,len[cur.pos]+1);
    for(int i=len[cur.pos]+1;i<=cur.mx;++i) ans[i+1]='1';
    return 1;
}
signed main(){
    freopen("wait.in","r",stdin); freopen("wait.out","w",stdout);
    n=read();
    for(int i=1;i<=n;++i){
        cin>>s[i];
        int slen=s[i].length();
        reverse(s[i].begin(),s[i].end());
        for(int j=0;j<slen;++j) ones+=s[i][j]=='1';
        ckmax(mxl,slen);
    }
    //radix sort
    for(int i=1;i<=n;++i) id[i]=i;
    int rem=n,pter=ones;
    for(int l=0;l<mxl;++l){
        int ord0=0,ord1=0;
        for(int j=1;j<=rem;++j) ord1+=s[id[j]][l]=='0';
        for(int j=1;j<=rem;++j){
            if(s[id[j]][l]=='0') nxt[++ord0]=id[j];
            else nxt[++ord1]=id[j];
        }
        rep(i,1,rem) id[i]=nxt[i];
        for(int i=1;i<=rem;++i){
            if(s[id[i]][l]=='1'){
                nxt[pter]=head[id[i]];
                head[id[i]]=pter;
                len[pter--]=l;
            }
        }
        int cnt=rem; rem=0;
        for(int j=1;j<=cnt;++j){
            if(s[id[j]].length()>l+1) id[++rem]=id[j];
        }
    }
    for(int i=1;i<=n;++i) vis[head[i]]=1;
    build(1,1,ones);
    int Len=n+mxl;
    rep(i,1,Len) ans[i]='0';
    solve(1,Len);
    while(Len>1&&ans[Len]!='1') --Len;
    for(int i=Len;i>=1;--i) putchar(ans[i]); putchar('\n');
    return 0;
}

标签:03,return,cur,int,sum,29,pos,2022,mx
来源: https://www.cnblogs.com/yspm/p/16073455.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有