2018-2019 ACM-ICPC Brazil Subregional Programming Contest

突突突 赶在暑假结束前 多搞搞队内训练

B. Marbles (unsolve)

根据题意我们能知道 谁到达(x,0) (0,x) (x,x) 谁就是必败点

我们把这三种情况排除 然后就变成了nim博弈了 谁先无法操作 谁就输了

#include<bits/stdc++.h>
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pb push_back
#define P pair<int,int>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 100005;
int sg[105][105],vis[205];
void get_sg(){
    for(int i=1;i<=100;i++)
     for(int j=1;j<=100;j++){
         if(i==j) continue;
         memset(vis,0,sizeof(vis));
         for(int k=1;k<=min(i-1,j-1);k++) 
            vis[sg[i-k][j-k]]=1;
         for(int k=1;k<=i-1;k++) 
            if(i-k!=j) 
            vis[sg[i-k][j]]=1;
         for(int k=1;k<=j-1;k++) 
            if(i!=j-k) 
            vis[sg[i][j-k]]=1;
         for(int k=0;;k++) 
            if(!vis[k]){ 
                sg[i][j]=k; 
                break;
         }
    }
}
int main(){
    get_sg();
    int n;
    cin>>n;
    int fg=0;
    int ans=0;
    while(n--){
        int x,y;
        cin>>x>>y;
        if(x==y){
            fg=1;
        }
        ans^=sg[x][y];
    }
    if(fg||ans){
        puts("Y");
    }else {
        puts("N");
    }
    return 0;
}
View Code

C. Pizza Cutter (solve)

题意:给你一个面基x*y的披萨  横着切h刀 竖着切v刀 题目保证了不会三刀交于一个点~

因为这个原因其实我们每次只需要求横着和竖着的逆序对 每个逆序对都会贡献+1 因为三刀不会交于一点所以正常切(没逆序对的情况下)

ans=(h+1)*(v+1) 然后加上逆序对即可

#include<bits/stdc++.h>
#define FIN freopen("input.txt","r",stdin)
#define ll long long
#define mod 1000000007
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define inf 0x3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
const int maxn = 100005;
using namespace std;
int n,m;
struct node{
    int x,y;
    bool friend operator<(const node u,const node v){
        return u.x<v.x;
    }
}p[maxn],q[maxn];
int a[maxn];
int tree[maxn];
int lowbit(int x){
    return x&(-x);
}
void add(int x){
    while(x<maxn){
        tree[x]++;
        x+=lowbit(x);
    }
}
int query(int x){
    int res=0;
    while(x){
        res+=tree[x];
        x-=lowbit(x);
    }
    return res;
}
ll solve(node *p,int n){
    sort(p+1,p+1+n);
    for(int i=1;i<=n;i++){
        a[i]=p[i].y;
    }
    memset(tree,0,sizeof(tree));
    sort(a+1,a+1+n);
    for(int i=1;i<=n;i++){
        p[i].y=lower_bound(a+1,a+1+n,p[i].y)-a;
    }
    ll ans=0;
    for(int i=1;i<=n;i++){
        add(p[i].y);
   //     cout<<i<<" "<<query(p[i].y)<<endl;
        ans+=i-query(p[i].y);
    }
    return ans;
}
int main(){
    int x,y;
    cin>>x>>y;
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        scanf("%d %d",&p[i].x,&p[i].y);
    }
    ll ans=0;
    ans+=solve(p,n);
    for(int i=1;i<=m;i++){
        scanf("%d %d",&q[i].x,&q[i].y);
    }
    ans+=solve(q,m);
    ans+=1LL*(n+1)*(m+1);
    cout<<ans<<"
";
    return 0;
}
View Code

D. Unraveling Monty Hall (solve)

题意:统一不是1的个数

E. Enigma (solve)

题意模拟就可以了

#include<bits/stdc++.h>
#define maxn 300005
#define mod 1000000007
using namespace std;
typedef long long ll;
char s1[maxn],s2[maxn];
int main(){
    scanf("%s%s",s1,s2);
    ll len1=strlen(s1);
    ll len2=strlen(s2);
    ll sum=0;
    for(int i=0;i<=len1-len2;i++){
        ll num=0;
        int k=i;
        for(int j=0;j<len2;j++){
            if(s1[k]==s2[j]) num++;
            k++;
        }
        if(num==0) sum++;
    } 
    cout<<sum;
}
View Code

F.Music Festiva (unsolve)

https://www.cnblogs.com/hua-dong/p/10350608.html(别问问就是付队博客)

I. Switches (solve)

题意:开始有L盏灯亮着 你有N个开关 每个开关控制着一些灯 每次使用开关会使灯开or关 

求按顺序按1~N个开关 能否关闭所有灯

思路:模拟最多两轮 因为第三轮的时候 第一轮和第二轮贡献抵消 所以前两轮没关掉 就没答案啦

#include<bits/stdc++.h>
#define maxn 300005
#define mod 1000000007
using namespace std;
typedef int ll;
bitset<1005> a[1005],q;
ll n,m;
ll len,x;
int main(){
    scanf("%d%d",&n,&m);
    scanf("%d",&len);
    for(int i=0;i<len;i++){
        scanf("%d",&x);
        q[x]=1;
    }
    for(int i=1;i<=n;i++){
        scanf("%d",&len);
        for(int j=0;j<len;j++){
            scanf("%d",&x);
            a[i][x]=1;
        }
    }
    ll sum=0;
    ll t=min(2,n);
    ll flag=0;
    for(int i=1;i<=t;i++){
        for(int j=1;j<=n;j++){
            q^=a[j];
            sum++;
            if(q.count()==0){
                flag=1;
                break;
            }
        }
        if(flag) break;
    }
    if(flag) printf("%d",sum);
    else printf("-1"); 
}
View Code
G. Gasoline (solve)

题意:

给你N个加油站 每个加油站需要ai的油 现在有M个油田可以提供油 接下来k条路用于油田到加油站的运输工作 且需要花费时间wi

每次运输量为无穷大且每个油田的车数量无穷大 让你求最少时间满足加油站的需求

思路:我们可以对于运输路径按wi排序 二分需要的路径数 也就是二分最大时间

每次check是否满流即可

View Code

L. Subway Lines (solve)

题意:给出一个树 然后求树上两条边的交集

思路:直接树剖 每次先插入第一条边 然后查询第二条边和即可

#include<bits/stdc++.h>
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pb push_back
#define P pair<int,int>
#define INF 1e18
using namespace std;
const int maxn = 100005;
int head[maxn],Next[maxn<<1],To[maxn<<1],fa[maxn],id[maxn],top[maxn],tp,pos[maxn];
int tot,cnt,size[maxn],son[maxn],deep[maxn],n;
int tree[maxn<<2],lazy[maxn<<2];
struct node{
    int u,v;
}p[100005];
void add(int u,int v){
    Next[++cnt]=head[u];
    head[u]=cnt;
    To[cnt]=v;
}
void dfs1(int u,int f,int dep){
    fa[u]=f;
    deep[u]=dep+1;
    int mx=0;
    for(int i=head[u]; i!=-1; i=Next[i]){
        int v=To[i];
        if(v==f) continue;
        dfs1(v,u,dep+1);
        size[u]+=size[v];
        if(size[v]>mx) mx=size[v],son[u]=v;
    }
    size[u]++;
}
void dfs2(int u,int tp){
    id[u]=++tot;
    pos[tot]=u;
    top[u]=tp;
    if(son[u]) dfs2(son[u],tp);
    for(int i=head[u]; i!=-1; i=Next[i]){
        int v=To[i];
        if(v!=son[u]&&v!=fa[u])
            dfs2(v,v);
    }
}
void push_up(int rt){
    tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
void push_down(int rt,int l,int r){
    if(lazy[rt]!=-1){
        lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt];
        int m=(l+r)>>1;
        tree[rt<<1]=(m-l+1)*lazy[rt];
        tree[rt<<1|1]=(r-m)*lazy[rt];
        lazy[rt]=-1;
    }
}
void update(int l,int r,int rt,int L,int R,int val){
    if(L<=l&&r<=R){
        tree[rt]=(r-l+1)*val;
        lazy[rt]=val;
       // cout<<rt<<" "<<val<<endl;
        return ;
    }
    push_down(rt,l,r);
    int m=(l+r)>>1;
    if(L<=m) update(lson,L,R,val);
    if(R>m) update(rson,L,R,val);
    push_up(rt);
}
int query(int l,int r,int rt,int L,int R){
   // i//f(l>r) return 0;
    if(tree[rt]==0) return 0;
    if(L<=l&&r<=R){
        return tree[rt];
    }
    int m=(l+r)>>1;
    push_down(rt,l,r);
    int sum=0;
    if(L<=m) sum+=query(lson,L,R);
    if(R>m) sum+=query(rson,L,R);
    push_up(rt);
    return sum;
}
void Update(int u,int v,int val){
     while(top[u]!=top[v]){
        if(deep[top[u]]<deep[top[v]]) swap(u,v);   // cout<<id[top[u]]<<" "<<id[u]<<endl;
        update(1,n,1,id[top[u]],id[u],val);
        u=fa[top[u]];
    }
     if(deep[u]>deep[v]) swap(u,v);
     update(1,n,1,id[u],id[v],val);
}
int Query(int u,int v){
    int sum=0;
    while(top[u]!=top[v]){
        if(deep[top[u]]<deep[top[v]]) swap(u,v);   // cout<<id[top[u]]<<" "<<id[u]<<endl;
        sum+=query(1,n,1,id[top[u]],id[u]);
        u=fa[top[u]];
    }
     if(deep[u]>deep[v]) swap(u,v);
     return sum+query(1,n,1,id[u],id[v]);
}
void init(){
    memset(head,-1,sizeof(head));
    memset(lazy,-1,sizeof(lazy));
}
int main(){
    int q;
    scanf("%d %d",&n,&q);
    init();
    for(int i=1; i<n; i++){
        scanf("%d %d",&p[i].u,&p[i].v);
        add(p[i].u,p[i].v);
        add(p[i].v,p[i].u);
    }
    dfs1(1,0,0);
    dfs2(1,1);
   // cout<<"?
";
    while(q--){
       int a,b,c,d;
       scanf("%d %d %d %d",&a,&b,&c,&d);// cout<<id[a]<<" "<<id[b]<<endl;
       Update(a,b,1);
     // cout<<"?
";
       printf("%d
",Query(c,d));
       Update(a,b,0);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/MengX/p/11381343.html