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

D. Dasha and Chess

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

#include 
using namespace std;
typedef long long ll;
typedef pair 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<>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 
using namespace std;
typedef long long ll;
typedef pair 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 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>1;
        if(check(mid)){ret=mid;rig=mid-1;}
        else lef=mid+1;
    }
    check(ret);
    vector 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 
using namespace std;
typedef long long ll;
typedef pair 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=0;i--){
        if(num>>i&1){
            if(p[i]==0){
                p[i]=num;pos[i]=ppp;
                break;
            }
            if(pos[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

你可能感兴趣的:(codeforces)