【补题计划】Codeforces Round #532 (Div. 2)

D. Dasha and Chess

交互题,黑白棋互奕,白棋与某个黑棋同行或者同列即可获胜。
利用棋盘大小和黑棋数量的性质就可以知道策略了。
移动白子到棋盘中心,然后往某个角落走,那么在500步内就能扫过棋盘的棋盘的3/4,而四等分棋盘后黑棋数量多的那三分是超过500个棋子的,所以往那个角落走一定能成功。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef unsigned long long ull;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
const int maxn=1000+15;
const int maxe=1e5+15;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;

int n,m;
pii pos[maxn];
int ma[maxn][maxn];
int tot=0;
void print(int a,int b){
    tot++;
    cout<<a<<" "<<b<<endl;
    cout.flush();
    int aa,bb,cc;
    cin>>aa>>bb>>cc;
    if(aa==-1||aa==0)exit(0);
    ma[pos[aa].fi][pos[aa].se]=0;
    pos[aa]=mp(bb,cc);
    ma[pos[aa].fi][pos[aa].se]=aa;
    if(tot==2000)exit(0);
}

int cntx,cnty;
int cc[4];
int main(){
    cin>>cntx>>cnty;
    for(int i=1,a,b;i<=666;i++){
        scanf("%d%d",&pos[i].fi,&pos[i].se);
        ma[pos[i].fi][pos[i].se]=i;
    }
    while(cntx<500){
        print(cntx+1,cnty);
        cntx++;
    }
    while(cntx>500){
        print(cntx-1,cnty);
        cntx--;
    }
    while(cnty<500){
        print(cntx,cnty+1);
        cnty++;
    }
    while(cnty>500){
        print(cntx,cnty-1);
        cnty--;
    }
    for(int i=1;i<=666;i++){
        if(pos[i].fi<500&&pos[i].se<500)cc[0]++;
        if(pos[i].fi<500&&pos[i].se>500)cc[1]++;
        if(pos[i].fi>500&&pos[i].se<500)cc[2]++;
        if(pos[i].fi>500&&pos[i].se>500)cc[3]++;
    }
    int mi=1000;
    for(int i=0;i<4;i++)mi=min(mi,cc[i]);
    int dx,dy;
    if(mi==cc[0]){dx=1;dy=1;}
    else if(mi==cc[1]){dx=1;dy=-1;}
    else if(mi==cc[2]){dx=-1;dy=1;}
    else {dx=-1;dy=-1;}
    while(1){
        if(ma[cntx+dx][cnty+dy]==0){
            print(cntx+dx,cnty+dy);
            cntx+=dx,cnty+=dy;
            continue;
        }
        print(cntx+dx,cnty);
        cntx+=dx;
        print(cntx,cnty+dy);
        cnty+=dy;
    }
    return 0;
}

E. Andrew and Taxi

消除图中的环,最小化最大所需翻转边的权值。
二分答案,小于mid的边无视掉,判剩余图是否能拓扑排序即可。
构造方案只要按照拓扑排序确定小于mid的边的顺序即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef unsigned long long ull;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
const int maxn=1e5+15;
const int maxe=1e5+15;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;

int n,m;

struct edge{
    int to,len,nxt,id;
}e[maxe];
int head[maxn];
int tot;

void adde(int u,int v,int len,int id){
    e[tot].to=v;
    e[tot].len=len;
    e[tot].id=id;
    e[tot].nxt=head[u];
    head[u]=tot++;
}


int id[maxn];
int deg[maxn];
bool check(int mid){
    memset(id,-1,sizeof(id));
    memset(deg,0,sizeof(deg));
    int idtot=1;
    for(int u=1;u<=n;u++){
        for(int i=head[u];i!=-1;i=e[i].nxt){
            if(e[i].len<=mid)continue;
            deg[e[i].to]++;
        }
    }
    queue<int> que;
    for(int i=1;i<=n;i++){
        if(deg[i]==0)que.push(i);
    }
    while(!que.empty()){
        int u=que.front();que.pop();
        id[u]=idtot++;
        for(int i=head[u];i!=-1;i=e[i].nxt){
            if(e[i].len<=mid)continue;
            int v=e[i].to;
            deg[v]--;
            if(deg[v]==0)que.push(v);
        }
    }
    if(idtot==n+1)return 1;
    return 0;
}

int main(){
    memset(head,-1,sizeof(head));
    scanf("%d%d",&n,&m);
    for(int i=0,a,b,c;i<m;i++){
        scanf("%d%d%d",&a,&b,&c);
        adde(a,b,c,i+1);
    }
    int lef=0,rig=1e9,ret;
    while(lef<=rig){
        int mid=(lef+rig)>>1;
        if(check(mid)){ret=mid;rig=mid-1;}
        else lef=mid+1;
    }
    check(ret);
    vector<int> vec;
    for(int u=1;u<=n;u++){
        for(int i=head[u];i!=-1;i=e[i].nxt){
            if(e[i].len>ret)continue;
            if(id[u]>id[e[i].to])vec.pb(e[i].id);
        }
    }
    sort(vec.begin(),vec.end());
    printf("%d %d\n",ret,vec.size());
    for(auto v:vec){
        printf("%d ",v);
    }
    return 0;
}

F. Ivan and Burgers
区间查询异或的最大值
离线,按照询问构造线性基,尽量让使用靠近右边的数构成线性基,然后询问就可以使用位置大于询问左边界的线性基贪心得出答案。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef unsigned long long ull;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
const int maxn=5e5+105;

int n,q;

struct query{
    int l,r,id;
}que[maxn];
bool cmp(query a,query b){
    return a.r<b.r;
}

int c[maxn];
int ans[maxn];


int p[21],pos[21];
void add(int num,int ppp){
    for(int i=20;i>=0;i--){
        if(num>>i&1){
            if(p[i]==0){
                p[i]=num;pos[i]=ppp;
                break;
            }
            if(pos[i]<ppp){
                swap(num,p[i]);
                swap(pos[i],ppp);
            }
            num^=p[i];
        }
    }
}

int query(int x){
    int ret=0;
    for(int i=20;i>=0;i--){
        if(pos[i]>=x&&(ret^p[i])>ret)ret^=p[i];
    }
    return ret;
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&c[i]);
    scanf("%d",&q);
    for(int i=0;i<q;i++){
        scanf("%d%d",&que[i].l,&que[i].r);
        que[i].id=i;
    }
    sort(que,que+q,cmp);
    int cnt=1;
    for(int i=0;i<q;i++){
        while(cnt<=que[i].r&&cnt<=n){
            add(c[cnt],cnt);
            cnt++;
        }
        ans[que[i].id]=query(que[i].l);
    }
    for(int i=0;i<q;i++)printf("%d\n",ans[i]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值