zoukankan      html  css  js  c++  java
  • 20182019 ACMICPC Brazil Subregional Programming Contest

    2018-2019 ACM-ICPC Brazil Subregional Programming Contest

    C. Pizza Cutter

    • 题意:一个矩形,给你一些横向纵向的边,问你能把矩形划分成多少区域?

    • 题解:打表找规律,答案为点数加边数+1,横纵交点能直接得到,同向交点即为两个方向的逆序对数量

    • 代码

      #include <bits/stdc++.h>
      #define ll long long
      #define fi first
      #define se second
      #define pb push_back
      #define me memset
      #define rep(a,b,c) for(int a=b;a<=c;++a)
      #define per(a,b,c) for(int a=b;a>=c;--a)
      const int N = 1e6 + 10;
      const int mod = 1e9 + 7;
      const int INF = 0x3f3f3f3f;
      using namespace std;
      typedef pair<int,int> PII;
      typedef pair<ll,ll> PLL;
      ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
      ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}
       
      int x,y;
      int h,v;
      ll c[N];
      PII a[N],b[N];
      vector<int> alla,allb;
      ll ans;
       
      int get_alla(int x){
          return lower_bound(alla.begin(),alla.end(),x)-alla.begin()+1;
      }
       
      int get_allb(int x){
          return lower_bound(allb.begin(),allb.end(),x)-allb.begin()+1;
      }
       
      ll lowbit(ll x){
          return x&(-x);
      }
       
      void update(int n,int i,int k){
          while(i<=n){
              c[i]+=k;
              i+=lowbit(i);
          }
      }
       
      ll query(int i){
          ll res=0;
          while(i){
              res+=c[i];
              i-=lowbit(i);
          }
          return res;
      }
       
       
      int main() {
          scanf("%d %d",&x,&y);
       
          scanf("%d %d",&h,&v);
       
          for(int i=1;i<=h;++i){
              scanf("%d %d",&a[i].fi,&a[i].se);
              alla.pb(a[i].se);
          }
          for(int i=1;i<=v;++i){
              scanf("%d %d",&b[i].fi,&b[i].se);
              allb.pb(b[i].se);
          }
          sort(a+1,a+1+h);
          sort(b+1,b+1+v);
          sort(alla.begin(),alla.end());
          sort(allb.begin(),allb.end());
          alla.erase(unique(alla.begin(),alla.end()),alla.end());
          allb.erase(unique(allb.begin(),allb.end()),allb.end());
          ans+=h+v+1ll*h*v;
          for(int i=1;i<=h;++i){
              int cur=get_alla(a[i].se);
              ans+=i-1-query(cur);
              update((int)alla.size(),cur,1);
          }
          me(c,0,sizeof(c));
          for(int i=1;i<=v;++i){
              int cur=get_allb(b[i].se);
              ans+=i-1-query(cur);
              update((int)allb.size(),cur,1);
          }
          printf("%lld\n",ans+1);
          return 0;
      }
      

    D. Unraveling Monty Hall

    签到

    #include <bits/stdc++.h>
    #define ll long long
    #define fi first
    #define se second
    #define pb push_back
    #define me memset
    #define rep(a,b,c) for(int a=b;a<=c;++a)
    #define per(a,b,c) for(int a=b;a>=c;--a)
    const int N = 1e6 + 10;
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    typedef pair<int,int> PII;
    typedef pair<ll,ll> PLL;
    ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}
     
    int n;
    int x;
     
    int main() {
        scanf("%d",&n);
        int ans=0;
        for(int i=1;i<=n;++i){
            scanf("%d",&x);
            if(x!=1) ans++;
        }
        printf("%d\n",ans);
        return 0;
    }
    

    E. Enigma

    签到

    #include <bits/stdc++.h>
    #define ll long long
    #define fi first
    #define se second
    #define pb push_back
    #define me memset
    #define rep(a,b,c) for(int a=b;a<=c;++a)
    #define per(a,b,c) for(int a=b;a>=c;--a)
    const int N = 1e6 + 10;
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    typedef pair<int,int> PII;
    typedef pair<ll,ll> PLL;
    ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}
     
    char t[N],s[N];
     
    int main() {
        scanf("%s",t+1);
        scanf("%s",s);
        int n=strlen(t+1),m=strlen(s);
        int ans=0;
        for(int i=1;i+m-1<=n;++i){
            bool flag=true;
            for(int j=0;j<m;++j){
                if(t[i+j]==s[j]){
                    flag=false;
                    break;
                }
            }
            if(flag) ans++;
        }
        printf("%d\n",ans);
        return 0;
    }
    

    F. Music Festival

    • 题意:有\(n\)个舞台,每个舞台都有不同的时间端进行表演,每个表演都有权值,你每个舞台都至少要观看一场演出,每个演出的时间段都不能相交,问你观看演出的最大权值为多少,如果不能每个舞台都观看则输出-1

    • 题解\(n\)最大只有\(10\),考虑状压dp,暴力枚举时间,\(dp[i][j]\)表示当前时间为\(i\),状态为\(j\)的最大权值,再枚举以当前时间为起点的演出,则:\(dp[r][j]=max(dp[r][j],dp[i][k]+w)\),\(r\)表示结束时间,\(j\)表示转移到的状态,\(k\)表示转移前的状态。

    • 代码

      #include <bits/stdc++.h>
      #define ll long long
      #define fi first
      #define se second
      #define pb push_back
      #define me memset
      #define rep(a,b,c) for(int a=b;a<=c;++a)
      #define per(a,b,c) for(int a=b;a>=c;--a)
      const int N = 1e6 + 10;
      const int mod = 1e9 + 7;
      const int INF = 0x3f3f3f3f;
      using namespace std;
      typedef pair<int,int> PII;
      typedef pair<ll,ll> PLL;
      ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
      ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}
       
      int n;
      struct Node{
          int r;
          int w;
          int id;
      }e;
      vector<Node> v[N];
      int dp[90000][1200];
       
      int main() {
          scanf("%d",&n);
          me(dp,-1,sizeof(dp));
          for(int i=1;i<=n;++i){
              int m;
              scanf("%d",&m);
              for(int j=1;j<=m;++j){
                  int l,r,w;
                  scanf("%d %d %d",&l,&r,&w);
                  v[l].pb({r,w,i});
              }
          }
          
          for(int i=1;i<=86400;++i){
             dp[i][0]=0;
             for(int j=1;j<(1<<n);++j){
                 dp[i][j]=max(dp[i][j],dp[i-1][j]);
             }
             for(int j=0;j<(int)v[i].size();++j){
                 for(int k=0;k<(1<<n);++k){
                      if(dp[i][k]==-1) continue;
                      int now=k|(1<<(v[i][j].id-1));
                      dp[v[i][j].r][now]=max(dp[v[i][j].r][now],dp[i][k]+v[i][j].w);
                 }
             } 
          }
          printf("%d\n",dp[86400][(1<<n)-1]);
          return 0;
      }
      

    I. Switches

    不难发现\(2n\)次后就复原了,所以枚举两次\(n\)模拟就好了。

    #include <bits/stdc++.h>
    #define ll long long
    #define fi first
    #define se second
    #define pb push_back
    #define me memset
    #define rep(a,b,c) for(int a=b;a<=c;++a)
    #define per(a,b,c) for(int a=b;a>=c;--a)
    const int N = 1e6 + 10;
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    typedef pair<int,int> PII;
    typedef pair<ll,ll> PLL;
    ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}
     
    int n,m;
    vector<int> v[N];
    unordered_map<int,int> mp;
     
    int main() {
        scanf("%d %d",&n,&m);
        int l;
        scanf("%d",&l);
        for(int i=1;i<=l;++i){
            int x;
            scanf("%d",&x);
            mp[x]=1;
        }
        for(int i=1;i<=n;++i){
            int k;
            scanf("%d",&k);
            for(int j=1;j<=k;++j){
                int x;
                scanf("%d",&x);
                v[i].pb(x);
            }
        }
        for(int i=1;i<=n;++i){
            for(auto w:v[i]){
                mp[w]=1-mp[w];
            }
            bool flag=true;
            for(int j=1;j<=m;++j){
                if(mp[j]==1){
                    flag=false;
                    break;
                }
            }
            if(flag){
                printf("%d\n",i);
                return 0;
            }
        }
        for(int i=1;i<=n;++i){
            for(auto w:v[i]){
                mp[w]=1-mp[w];
            }
            bool flag=true;
            for(int j=1;j<=m;++j){
                if(mp[j]==1){
                    flag=false;
                    break;
                }
            }
            if(flag){
                printf("%d\n",n+i);
                return 0;
            }
        }	
        puts("-1");
        return 0;
    }
    

    L. Subway Lines

    • 题意:一颗\(n\)个结点的树,\(q\)个询问,每次给你\(4\)个点,代表两条路径,问你两条路径的交点数

    • 题解:树上边的问题,不难想到树链剖分,分别对两条路径更新,在线段树将路径上的点+1,然后再查询任意一条路径,路径上权值为2的点即为两条路径相交的点

    • 代码

      #include <bits/stdc++.h>
       
      using namespace std;
      const int N=1e6+10;
      #define ll long long
      #define pb push_back
      int n,q;
      int dep[N],f[N],son[N],sz[N],wt[N],top[N],id[N],cnt;
      vector<int> edge[N];
       
      struct Node{
          int l,r;
          int cnt,tag,sum;
          int f;
      }tr[N<<4];
       
      void push_up(int u){
          tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum;
      }
       
      void push_down(int u){
          if(tr[u].f){
              tr[u<<1].cnt=tr[u<<1].tag=tr[u<<1].sum=0;
              tr[u<<1|1].cnt=tr[u<<1|1].tag=tr[u<<1|1].sum=0;
              tr[u<<1].f=tr[u<<1|1].f=1;
              tr[u].f=0;
          }
          if(tr[u].tag){
              tr[u<<1].cnt+=tr[u].tag;
              if(tr[u<<1].cnt==2) tr[u<<1].sum=tr[u<<1].r-tr[u<<1].l+1;
              tr[u<<1].tag+=tr[u].tag;
       
              tr[u<<1|1].cnt+=tr[u].tag;
              if(tr[u<<1|1].cnt==2) tr[u<<1|1].sum=tr[u<<1|1].r-tr[u<<1|1].l+1;
              tr[u<<1|1].tag+=tr[u].tag;
       
              tr[u].tag=0;
          }
      }
       
      void build(int u,int l,int r){
          if(l==r){
              tr[u]={l,r,0,0,0,0};
              return;
          }
          tr[u]={l,r,0,0,0,0};
          int mid=(l+r)>>1;
          build(u<<1,l,mid);
          build(u<<1|1,mid+1,r);
          push_up(u);
      }
       
      void update(int u,int L,int R,int f){
          if(tr[u].l>=L && tr[u].r<=R){
              if(f){
                  tr[u].cnt=tr[u].sum=0;
                  tr[u].f=1;
                  return;
              }
              tr[u].cnt++;
              tr[u].tag++;
              if(tr[u].cnt==2) tr[u].sum=(tr[u].r-tr[u].l+1);
              return;
          }
          push_down(u);
          int mid=(tr[u].l+tr[u].r)>>1;
          if(L<=mid) update(u<<1,L,R,f);
          if(R>mid) update(u<<1|1,L,R,f);
          push_up(u);
      }
       
      int query(int u,int L,int R){
          if(tr[u].l>=L && tr[u].r<=R) return tr[u].sum;
          push_down(u);
          int mid=(tr[u].l+tr[u].r)>>1;
          int res=0;
          if(L<=mid) res+=query(u<<1,L,R);
          if(R>mid) res+=query(u<<1|1,L,R);
          return res;
      }
       
      void dfs1(int u,int fa,int deep){
          dep[u]=deep;
          f[u]=fa;
          sz[u]=1;
          int mxson=-1;
          for(auto to:edge[u]){
              if(to==fa) continue;
              dfs1(to,u,deep+1);
              sz[u]+=sz[to];
              if(sz[to]>mxson) son[u]=to,mxson=sz[to];
          }
      }
       
      void dfs2(int u,int topf){
          id[u]=++cnt;
          wt[cnt]=1;
          top[u]=topf;
          if(!son[u]) return;
          dfs2(son[u],topf);
          for(auto to:edge[u]){
              if(to==f[u] || to==son[u]) continue;
              dfs2(to,to);
          }
      }
       
      void updrange(int x,int y){
          while(top[x]!=top[y]){
              if(dep[top[x]]<dep[top[y]]) swap(x,y);
              update(1,id[top[x]],id[x],0);
              x=f[top[x]];
          }
          if(dep[x]>dep[y]) swap(x,y);
          update(1,id[x],id[y],0);
      }
       
      int queryrange(int x,int y){
          int ans=0;
          int res=0;
          while(top[x]!=top[y]){
              if(dep[top[x]]<dep[top[y]]) swap(x,y);
              res=query(1,id[top[x]],id[x]);
              ans+=res;
              x=f[top[x]];
          }
          if(dep[x]>dep[y]) swap(x,y);
          res=query(1,id[x],id[y]);
          ans+=res;
          return ans;
      }
       
      int main(){
          scanf("%d %d",&n,&q);
       
          for(int i=1;i<n;++i){
              int u,v;
              scanf("%d %d",&u,&v);
              edge[u].pb(v);
              edge[v].pb(u);
          }
          dfs1(1,0,1);
          dfs2(1,1);
          build(1,1,n);
          while(q--){
              int a,b,c,d;
              scanf("%d %d %d %d",&a,&b,&c,&d);
              updrange(a,b);
              updrange(c,d);
              printf("%d\n",queryrange(a,b));
              update(1,1,n,1);
          }
          return 0;
      }
      
  • 相关阅读:
    yii2中的url美化
    一级域名301重定向到www二级域名
    使用meta来控制浏览器的渲染方式
    同一页面不同编码的提交处理
    Yii2.0 UrlManager
    sqlsever连接两个不同服务器上的数据库进行查询
    php 实现传入参数的传出
    xcode如何修改项目名称
    ios如何实现应用之间的跳转
    ios程序如何实现系统自带的分享
  • 原文地址:https://www.cnblogs.com/lr599909928/p/15587388.html
Copyright © 2011-2022 走看看