Codeforces Round #361 (Div. 2) 套题

A - Mike and Cellphone

问有没有多解,每个点按照给出的序列用向量法跑一遍

#include<cstdio>
#include<cstring>
#include<queue>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<cmath>
#include<map>
using namespace std;
typedef long long LL;
const int N=2e5+5;
const int INF=0x3f3f3f3f;
char s[15];
int a[15],n;
int mp[5][4]={-1,-1,-1,-1,
               -1,1,2,3,
               -1,4,5,6,
               -1,7,8,9,
               -1,-1,0,-1
             };
typedef pair<int,int> pii;
pii pos[10];
bool judge(int num){
  int x=pos[num].first,y=pos[num].second;
  for(int i=2;i<=n;++i){
    int px=pos[a[i]].first-pos[a[i-1]].first;
    int py=pos[a[i]].second-pos[a[i-1]].second;
    x+=px;y+=py;
    if(x<1||x>4||y<1||y>3)return false;
    if(mp[x][y]==-1)return false;
  }
  return true;
}
int main(){
  scanf("%d%s",&n,s+1);
  if(n==1){printf("NO\n");return 0;}
  for(int i=1;i<=n;++i)
    a[i]=s[i]-'0';
  for(int i=1;i<=4;++i){
    for(int j=1;j<=3;++j){
      if(mp[i][j]==-1)continue;
       pos[mp[i][j]].first=i;
       pos[mp[i][j]].second=j;
    }
  }
  bool flag=false;
  for(int i=0;i<=9;++i)
    if(i!=a[1]&&judge(i)){flag=true;break;}
  if(flag)printf("NO\n");
  else printf("YES\n");
  return 0;
}
View Code

B - Mike and Shortcuts

可能有更优的办法,一看数据,dij最短路水过

#include<cstdio>
#include<cstring>
#include<queue>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<cmath>
#include<map>
using namespace std;
typedef long long LL;
const int N=2e5+5;
const int INF=0x3f3f3f3f;
struct Edge{
   int v,next;
   LL w;
   Edge(int a=0,LL b=0){v=a,w=b;}
   bool operator<(const Edge &e)const{
      return w>e.w;
   } 
}edge[N*3];
int head[N],tot,n;
LL d[N];
void add(int u,int v,int w){
   edge[tot].v=v;
   edge[tot].w=w;
   edge[tot].next=head[u];
   head[u]=tot++;
}
priority_queue<Edge>q;
bool vis[N];
void dij(int s){
    for(int i=1;i<=n;++i)d[i]=INF,vis[i]=0;
    d[s]=0,q.push(Edge(s,0));
    while(!q.empty()){
       int u=q.top().v;
       q.pop();
       if(vis[u])continue;
       vis[u]=1;
       for(int i=head[u];~i;i=edge[i].next){
          int v=edge[i].v;
          if(!vis[v]&&d[v]>d[u]+edge[i].w){
            d[v]=d[u]+edge[i].w;
            q.push(Edge(v,d[v]));
          }
       } 
    }
}
int main(){
  scanf("%d",&n);
  memset(head,-1,sizeof(head));
  for(int i=1;i<=n;++i){
     int x;scanf("%d",&x);
     add(i,x,1);
  }
  for(int i=1;i<n;++i){
    add(i,i+1,1);
    add(i+1,i,1);
  }
  dij(1);
  for(int i=1;i<n;++i)printf("%I64d ",d[i]);
  printf("%I64d\n",d[n]);
  return 0;
}
View Code

C - Mike and Chocolate Thieves

直接二分找就行,注意二分的移动

#include<cstdio>
#include<cstring>
#include<queue>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<cmath>
#include<map>
using namespace std;
typedef long long LL;
const int N=2e5+5;
const int INF=0x3f3f3f3f;
LL judge(LL mid){
  LL sum=0;
  for(LL i=2;i<=1000000;++i){
   sum+=mid/(i*i*i);
  }
  return sum;
}
int main(){
  LL m;
  scanf("%I64d",&m);
  LL l=1,r=1ll*1e18,ret=-1;
  while(l<=r){
    LL mid=(l+r)>>1; 
    LL tmp=judge(mid);
    if(tmp>m)r=mid-1;
    else if(tmp==m)ret=mid,r=mid-1;
    else l=mid+1;
  }
  printf("%I64d\n",ret);
  return 0;
}
View Code

D - Friends and Subsequences

这个题,不知道是我线段树写残了,还是线段树常数大,死活超时,RMQ才过,哪天去学一发ZKW线段树的姿势吧

#include <vector>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <cstring>
#include <algorithm>
#include <cstdio>

using namespace std;
#define For(i,j,n) for(int i=j;i<=n;i++)
#define Riep(n) for(int i=1;i<=n;i++)
#define Riop(n) for(int i=0;i<n;i++)
#define Rjep(n) for(int j=1;j<=n;j++)
#define Rjop(n) for(int j=0;j<n;j++)
#define mst(ss,b) memset(ss,b,sizeof(ss));
typedef  long long LL;
template<class T> void read(T&num) {
    char CH; bool F=false;
    for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar());
    for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar());
    F && (num=-num);
}
int stk[70], tp;
template<class T> inline void print(T p) {
    if(!p) { puts("0"); return; }
    while(p) stk[++ tp] = p%10, p/=10;
    while(tp) putchar(stk[tp--] + '0');
    putchar('\n');
}

const LL mod=1e9+7;
const double PI=acos(-1.0);
const LL inf=1e18;
const int N=2e5+10;
const int maxn=1005;
const double eps=1e-10;

int a[N],b[N],MX[N][21],MN[N][21],n;
struct Tree
{
    int l,r;
    int mmax,mmin;
}tr[4*N];

void build(int o,int L,int R)
{
    for(int i=1;i<=n;i++)
    MX[i][0]=a[i],MN[i][0]=b[i];
    for(int j=1;(1<<j)<=n;j++)
    {
        for(int i=1;i+(1<<j)-1<=n;i++)
        {
            MX[i][j]=max(MX[i][j-1],MX[i+(1<<(j-1))][j-1]);
            MN[i][j]=min(MN[i][j-1],MN[i+(1<<(j-1))][j-1]);
        }
    }
}
int query(int o,int L,int R,int flag)
{
    if(flag)
    {
        int k = 0;
        while( (1<<(k+1)) <= R-L+1) k ++ ;
        return max(MX[L][k],MX[R-(1<<k)+1][k]);
    }
    else
    {
        int k = 0;
        while( (1<<(k+1)) <= R-L+1) k ++ ;
        return min(MN[L][k],MN[R-(1<<k)+1][k]);
    }
}
int judge(int x,int y)
{
    int mx=query(1,x,y,1),mn=query(1,x,y,0);
   if(mx==mn)return 1;
  else if(mx>mn)return 2;
  return 0;
  
}
int main()
{
    read(n);
    For(i,1,n)read(a[i]);
    For(i,1,n)read(b[i]);
    build(1,1,n);
     LL ret=0;
  for(int i=1;i<=n;++i){
    int ans1=-1,ans2=-1;
    int l=i,r=n;
    while(l<=r){
      int m=l+r>>1;
      int t=judge(i,m);
      if(t==1)ans1=m,r=m-1;
      else if(t==2)r=m-1;
      else l=m+1;
    }
    l=i,r=n;
    while(l<=r){
      int m=l+r>>1;
      int t=judge(i,m);
      if(t==1)ans2=m,l=m+1;
      else if(t==2)r=m-1;
      else l=m+1;
    }
    if(ans1!=-1&&ans2!=-1)ret+=ans2-ans1+1;
  }
  printf("%I64d\n",ret);
        return 0;
}
View Code

E - Mike and Geometry Problem

区间题,转化一下,看每个点被多少个线段覆盖(离散化搞搞),相同覆盖数统计,然后用组合数就行

#include <vector>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
typedef long long LL;
const int N=2e5+5;
const LL mod=1e9+7;
struct Segment{
   int l,r;
}p[N];
int pos[N*2],n,k,tot,a[N*2],b[2*N];
LL dp[N],fac[N],inv[N];
LL quick_pow(LL a,LL num){
  LL ret=1;
  while(num){
    if(num&1)ret=(ret*a)%mod;
    num>>=1;
    a=(a*a)%mod;
  }
  return ret;
}
LL C(LL n,LL m){
  return (fac[n]*inv[n-m])%mod*inv[m]%mod;
}
int main()
{
    scanf("%d%d",&n,&k);    
    inv[0]=fac[0]=1;
    for(int i=1;i<=n;++i){
        fac[i]=1ll*i*fac[i-1]%mod;
        inv[i]=quick_pow(fac[i],mod-2);
    } 
    for(int i=1;i<=n;++i){
      scanf("%d%d",&p[i].l,&p[i].r);
      pos[++tot]=p[i].l;
      pos[++tot]=p[i].r;
    }
    sort(pos+1,pos+1+tot);
    tot=unique(pos+1,pos+1+tot)-pos-1;
    for(int i=1;i<=n;++i){
      p[i].l=lower_bound(pos+1,pos+1+tot,p[i].l)-pos;
      p[i].r=lower_bound(pos+1,pos+1+tot,p[i].r)-pos;
      ++a[p[i].l],--b[p[i].r];
    }
    for(int i=1;i<=tot;++i){
      a[i]+=a[i-1];
      ++dp[a[i]];
      if(i!=1)dp[a[i-1]]+=max(0,pos[i]-pos[i-1]-1);
      a[i]+=b[i];
    }
    LL ret=0;
    for(int i=k;i<=n;++i){
       ret=(ret+dp[i]*C(i,k)%mod)%mod;
    }
    printf("%I64d\n",ret);
    return 0;
}
View Code

 

posted @ 2016-07-11 14:22  shuguangzw  阅读(156)  评论(0编辑  收藏  举报