向地学青苔|

EdGrass

园龄:2年1个月粉丝:10关注:4

Educational Codeforces Round 138 (Rated for Div. 2)

A.CowardlyRooks

我模拟了一遍,因为我没看到题目中给出的矩阵已经合法a 题第一次写这么多。
实验室同事跟我说只要判断 nm 的大小关系就行了。

int x[N],y[N],m,n;
bool check(){
    for(int i=1;i<=m;i++){
        for(int j=1;j<=m;j++){
            if(i==j)continue;
            if(x[i]==x[j]||y[i]==y[j])return false;
        }
    }
    return true;
}
void solve(){
    n=read(),m=read();
    int ans=0;
    for(int i=1;i<=m;i++){
        x[i]=read();
        y[i]=read();
    }
    for(int i=1;i<=m;i++){
        int tx=x[i],ty=y[i];
        for(int j=1;j<=n;j++){
            if(j==ty)continue;
            x[i]=tx;
            y[i]=j;
            if(check())ans=1;
        }
        for(int j=1;j<=n;j++){
            if(j==tx)continue;
            x[i]=j;
            y[i]=ty;
            if(check())ans=1;
        }
        x[i]=tx;
        y[i]=ty;
    }
    puts(ans==1?"YES":"NO");
    //puts(ans>0?"Yes":"No");
}

B.DeathsBlessing

看了下题,感觉每次删掉前面和后面更小的一个就行了。
要从中间删会被计算两次,而头尾只会被计算一次。因为最后只会剩下一个数,所以可以让最大的数留下来。

void solve(){
    int n=read(),sum=0;
    for(int i=1;i<=n;i++){
        sum+=read();
    }
    deque<int>a;
    for(int i=1;i<=n;i++){
        a.push_back(read());
    }
    for(int i=1;i<n;i++){
        if(a.front()<=a.back()){
            sum+=a.front();
            a.pop_front();
        }else{
            sum+=a.back();
            a.pop_back();
        }
    }
    cout<<sum<<'\n';
    //puts(ans>0?"YES":"NO");
    //puts(ans>0?"Yes":"No");
}

C.NumberGame

本题可以用二分答案,在 check 里面用 multiset 模拟一遍。但是数据太小可以直接枚举。

void solve(){
    int n=read(),ans=0;
    multiset<int>st;
    for(int i=1;i<=n;i++){
        st.insert(read());
    }
    for(int k=1;k<=n;k++){
        multiset<int>tp(st);
        int ok=1;
        for(int i=1;i<=k;i++){
            int x=k-i+1;
            while(tp.upper_bound(x)!=tp.end()) 
                tp.erase(tp.upper_bound(x));
            if(tp.size()==0){
                ok=0;
                break;
            }
            auto it=tp.upper_bound(x);
            it--;
            tp.erase(it);
            if(tp.size()){
                tp.erase(tp.begin());
            }
            x--;
        }
        if(ok)ans=k;
    }
    cout<<ans<<'\n';
    //puts(ans>0?"YES":"NO");
    //puts(ans>0?"Yes":"No");
}

D.CountingArrays

思考什么样的数列会是 ambiguous 的,显然是后面的数字与 i 的连积的 gcd1。那么明显的非 ambiguous 数字更好求,每次算当前位有多少种方案是连积的倍数,然后容斥减掉。

int primes[N], cnt;
bool st[N];    
void get_primes(int n){
    for (int i = 2; i <= n; i ++ ){
        if (!st[i]) primes[cnt ++ ] = i;
        for (int j = 0; primes[j] <= n / i; j ++ ){
            st[primes[j] * i] = true;
            if (i % primes[j] == 0) break;
        }
    }
}
int fac[N];
void init(){
    get_primes(N-1);
    fac[1]=1;
    for(int i=2;i<N;i++){
        fac[i]=fac[i-1];
        if(!st[i])fac[i]*=i;
        // fac[i]=mod;
    }
}
void solve(){
    int n=read(),m=read();
    mint tol=0,ans=1,sum=1;
    for(int i=1;i<=n;i++){
        sum*=m;
        ans*=(m/fac[i]);
        tol+=sum-ans;
    }
    cout<<tol<<'\n';
    //puts(ans>0?"YES":"NO");
    //puts(ans>0?"Yes":"No");
}

E.CactusWall

那么转换题意,就是要求一条从左边到右边可以横穿的仙人掌路,而且路还得斜着走。那么对于已经有仙人掌的点点权记为 0 ,对于没有的点点权记为 1 ,这样就是求一个从左端到右端的最短路,可以在 01 图上跑双端 bfs

struct node{
    int x,y;
};
const int dx[]={0,0,1,-1,1,1,-1,-1};
const int dy[]={1,-1,0,0,1,-1,1,-1};
deque<node>q;
vector<int>pre[N],d[N];
string mp[N];
int n,m;
bool check(int x,int y){
    if(x<0||x>=n||y<0||y>=m)return false;
    for(int i=0;i<4;i++){
        int xx=x+dx[i],yy=y+dy[i];
        if(xx>=0&&xx<n&&yy>=0&&yy<m&&mp[xx][yy]=='#')return false;
    }
    return true;
}
void bfs(){
    while(!q.empty()){
        int x=q.front().x,y=q.front().y;
        q.pop_front();
        for(int i=4;i<8;i++){
            int xx=x+dx[i],yy=y+dy[i]; 
            if(!check(xx,yy))continue;
            int s=(mp[xx][yy]=='.');
            if(d[xx][yy]>d[x][y]+s){
                d[xx][yy]=d[x][y]+s;
                pre[xx][yy]=i;
                if(s)q.push_back((node){xx,yy});
                else q.push_front((node){xx,yy});
            }
        }
    }
}
void solve(){
    n=read(),m=read();
    for(int i=0;i<n;i++){
        cin>>mp[i];
    }
    for(int i=0;i<n;i++){
        pre[i].clear();
        d[i].clear();
        for(int j=0;j<m;j++){
            d[i].push_back(inf);
            pre[i].push_back(0);
        }
        if(mp[i][0]=='#')q.push_front((node){i,0}),d[i][0]=0;
        else if(check(i,0))q.push_back((node){i,0}),d[i][0]=1;
    }
    bfs();
    int minn=inf,mini=-1;
    for(int i=0;i<n;i++){
        if(d[i][m-1]<minn){
            minn=d[i][m-1];
            mini=i;
        }        
    }
    if(mini==-1){
        cout<<"NO\n";
        return ;
    }
    cout<<"YES\n";
    int x=mini,y=m-1;
    while(1){
        mp[x][y]='#';
        if(!pre[x][y])break;
        int lst=pre[x][y];
        x-=dx[lst];y-=dy[lst];
    }
    for(int i=0;i<n;i++){
        cout<<mp[i]<<'\n';
    }
    //puts(ans>0?"YES":"NO");
    //puts(ans>0?"Yes":"No");
}

F.DistancetothePath

对于修改操作可以先对路径标记,用树状数组 +dfs 序标记。具体的就是对 dfs 序上的 fenwick[x]fenwick[y]+d ,对 fenwick[lca(x,y)]2d ,然后询问的时候对 x 入队和出队的地方进行差分。以上只是子树内的处理,而对子树外的点可以归结为 lca 的贡献,对单点进行暴力修改,记录 dp[i][j] 表示 [i] 的位置向外 [j] 个距离加上修改值,并且向上转移,每次转移会重复计算下面的点,容斥处理。
子树内修改为 O(qlogn) ,查询为 O(qdlogn) 。子树外修改和查询都为为 O(qd) ,最后的复杂度类似于 O(nlog2n)

vector<int>adj[N+5];
int f[N+5][21],n,m;
int son[N+5],siz[N+5],father[N+5],top[N+5],in[N+5],out[N+5],dep[N+5],timer;
struct Fenwick {
    int c[N+5];
    inline int lowbit(int x) {return x&(-x);}
    inline void add(int x,int d) {
        for(;x<=n;x+=lowbit(x))c[x]+=d;
    }
    inline int query(int x) {
        int res=0;
        for(;x>=1;x-=lowbit(x))res+=c[x];
        return res;
    }
    inline int rangequery(int l,int r) {
        return query(r)-query(l-1);
    }
}fen[21];
void dfs1(int u,int fa) {
    siz[u]=1,father[u]=fa,dep[u]=dep[fa]+1;    
    int mx=0;
    for(int v:adj[u]) 
        if(v!=fa) {
            dfs1(v,u);
            if(siz[v]>mx)son[u]=v,mx=siz[v];
            siz[u]+=siz[v];
        }
}
void dfs2(int u,int fa,int now) {
    top[u]=now,in[u]=++timer;
    if(son[u])dfs2(son[u],u,now);
    for(int v:adj[u])
        if(v!=son[u]&&v!=fa)dfs2(v,u,v);
    out[u]=timer;
}
inline int lca(int x,int y) {
    while(top[x]!=top[y]) {
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        x=father[top[x]];
    }
    if(dep[x]>dep[y])swap(x,y);
    return x;
}
inline void modify(int x,int y,int k,int d) {
    int z=lca(x,y);
    fen[k].add(in[x],d);
    fen[k].add(in[y],d);
    fen[k].add(in[z],-2*d);
    for(int i=0;i<=k&&z;i++) {
        f[z][k-i]+=d;
        if(k-i-2>=0&&z!=1)f[z][k-i-2]-=d;
        z=father[z];
    }
}
inline int query(int x) {
    int res=0,dis=0;
    for(int i=0;i<=20&&x;i++) {
        res+=fen[i].rangequery(in[x],out[x]);
        for(int j=dis;j<=20;j++)res+=f[x][j];
        ++dis,x=father[x];
    }
    return res;
}
void solve() {
    n=read();
    for(int i=1;i<n;i++) {  //build edge
        int x=read(),y=read();
        adj[x].push_back(y);
        adj[y].push_back(x);
    }
    dfs1(1,0),dfs2(1,0,1);  //build lca
    m=read();
    while(m--) {   
        int op=read();
        if(op==1) {
            int x=read();
            cout<<query(x)<<'\n';
        }
        else {
            int x=read(),y=read(),d=read(),k=read();    //distance is k   add d
            modify(x,y,k,d);
        }
    }
}

本文作者:EdGrass

本文链接:https://www.cnblogs.com/edgrass/p/17686188.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   EdGrass  阅读(25)  评论(0编辑  收藏  举报
   
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 影子 岛屿心情
影子 - 岛屿心情
00:00 / 00:00
An audio error has occurred.

作词 : 张龙/史维旭/刘博宽/格桑咸俊

作曲 : 张龙/史维旭/刘博宽/格桑咸俊

编曲:岛屿心情

总是迷恋水中倒映的自己

总是迷恋水中倒映的自己

总会为你穿上漂亮的外衣

在云端坠落后不堪一击

却仍旧搭起虚幻的云梯

直到没有什么能使你满意

直到没有什么能使你满意

直到那些伤口不再能痊愈

你早已失去了爱的能力

这里的风景还能有什么意义

这是我今生的

这是我今生的

这是我仅剩的

要为你准备多少才将我抛弃

我让你娱乐做你的工具

你可以轻松毁掉一切并嫁祸于我

你可以轻松毁掉一切并嫁祸于我

在这间屋子里我什么都不能说

我爱啊恨啊醉啊

你荡啊荡啊追啊

我是你的影子

我是你的影子

我透过影子追逐你

我透过影子追逐你

我透过影子追逐你

我透过影子追逐你

我透过影子追逐你

我透过影子追逐你

(我早已)

我透过影子追逐你

(看穿了你)

我透过影子追逐你

(我早已)

我透过影子追逐你

(看穿了你)

我透过影子追逐你

(我早已)

我透过影子追逐你

(看穿了你)

我透过影子追逐你

(我不再)

我透过影子追逐你

(不再怕你)

制作人:王大治

制作人:王大治

录音师:杨森 B2

混音师:王大治

录音棚:时音唱片

母带后期:时音唱片