BestCoder Round#77

博主分享了在BestCoder Round #77中的题目解析,涉及题目包括1001到1005。讨论了在不同问题中运用的算法,如枚举子集、排列组合、并查集、动态规划和树状数组等。对于部分题目,博主提出了离线处理的方法来优化复杂度,特别提到了离线做法在1005题中的应用。总结认为这场竞赛相对简单,并表达了对Manchery的帮助的感激。
摘要由CSDN通过智能技术生成

今天开始将要转一下做题的OJ了。。
虽然感觉放着权限号在那里不好。。。。。

然后先写一下BC #77的题解吧

1001
就是在枚举子集的过程中我们发现当n > 1时,x出现了偶数次,所以其对答案的贡献就是0;当 n = 1时,其对答案的贡献是 x

1002
简单的排列组合

1003
考虑离线之后我们就可以用并查集做了

1004
DP 是可以用单调队列优化成 O(n) 的 不过我打的是 O(n2)

1005
这一题可以考虑离线
离线做法很经典 先将询问按R排序 然后就可以在树状数组上修改了
在线的话代码量可能比较大 就是用可持久话线段树 具体思想和那个询问[l,r]区间的边形成几个联通块差不多

总的来说这一场还是比较水的
PS:感谢这一场带我飞的Manchery大爷

1001

#include<cstdio>
#include<cstdlib>
using namespace std;

inline char nc()
{
    static char buf[100000],*p1=buf,*p2=buf;
    if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
    return *p1++;
}
#define ll long long
inline void read(ll &x)
{
    char c=nc(),b=1;
    for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
    for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

ll n,a,ans;
int main()
{
    ll Q;
    read(Q);
    while (Q--)
    {
        read(n);
        for (ll i=1;i<=n;i++)
            read(a);
        if (n>1) 
            ans=0;
        else 
            ans=a;
        printf("%I64d\n",ans);
    }
    return 0;
}

1002

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cstring>

const int maxn = 1005;
const int mod = 1e9 + 7;

int n;
int cnt[30];
char s[maxn];
int c[maxn][maxn];

int main()
{
    int T;


    scanf("%d", &T);

    c[1][0] = c[1][1] = 1;
    for(int i = 2; i <= 1000; i++)
    {
        c[i][0] = 1;

        for(int j = 1; j <= i; j++)
            (c[i][j] = c[i - 1][j - 1] + c[i - 1][j]) %= mod;
    }

    while(T--)
    {
        scanf("%s", s + 1);
        n = strlen(s + 1);

        memset(cnt, 0, sizeof(cnt));

        for(int i = 1; i <= n; i++)    cnt[s[i] - 'a' + 1]++;

        int odd = 0;

        for(int i = 1; i <= 26; i++) odd += cnt[i] & 1;

        if(odd > 1) puts("0");
        else
        {
            int tot = 0;
            long long ans = 1;

            for(int i = 1; i <= 26; i++)
            {    
                cnt[i] /= 2;

                if(cnt[i])
                {
                    (ans *= c[cnt[i] + tot][cnt[i]]) %= mod;
                    tot += cnt[i];
                }
            }

            cout << ans << std;
        }
    }
    return 0;
}

1003

#include<cstdio>
#include<cstdlib>
#include<cstring>
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
#define ll long long
inline char nc()
{
    static char buf[100000],*p1=buf,*p2=buf;
    if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
    return *p1++;
}

inline void read(int &x)
{
    char c=nc(),b=1;
    for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
    for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

inline int read(char *s)
{
    char c=nc(); int len=0;
    for (;!(c>='0' && c<='1');c=nc());
    for (;c>='0' && c<='1';s[++len]=c,c=nc()); s[++len]=0; return len-1;
}

int n,m,S,T,K;
int fat[250005];
char M[505][505];
int X[250005],Y[250005];
const int dx[]={0,0,1,-1};
const int dy[]={1,-1,0,0};

inline int P(int x,int y){
    if (x==0) return S;
    if (x==n+1) return T;
    return (x-1)*m+y;
}

inline int getfat(int u){
    return u==fat[u]?u:fat[u]=getfat(fat[u]);
}

inline void link(int x,int y){
    int fx=getfat(x),fy=getfat(y);
    if (fx!=fy)
        fat[fx]=fy;
}

inline bool Jud(int x,int y){
    int fx=getfat(x),fy=getfat(y);
    return fx==fy;
}

int main()
{
    int Q;
    read(Q);
    while (Q--)
    {
        read(n); read(m); S=n*m+1; T=n*m+2;
        for (int i=1;i<=n;i++)
            read(M[i]);
        read(K);
        for (int i=1;i<=K;i++) read(X[i]),read(Y[i]),X[i]++,Y[i]++,M[X[i]][Y[i]]='1';
        for (int i=1;i<=T;i++) fat[i]=i;
        for (int i=1;i<=n;i++)
            for (int j=1;j<=m;j++)
                if (M[i][j]!='1')
                {
                    int a,b;
                    for (int k=0;k<4;k++)
                    {
                        a=i+dx[k],b=j+dy[k];
                        if (b>0 && b<=m)
                            if (a==0 || a==n+1 || M[a][b]!='1')
                                link(P(a,b),P(i,j));
                    }
                }
        if (Jud(S,T)){
            printf("-1\n");
            continue;
        }
        int flag=0;
        for (int i=K;i && !flag;i--)
        {
            int a,b;
            for (int k=0;k<4;k++)
            {
                a=X[i]+dx[k],b=Y[i]+dy[k];
                if (b>0 && b<=m)
                    if (a==0 || a==n+1 || M[a][b]!='1')
                        link(P(a,b),P(X[i],Y[i]));
            }
            M[X[i]][Y[i]]='0';
            if (Jud(S,T)){
                printf("%d\n",i);
                flag=1;
            }
        }
        if (!flag)
            printf("0\n");    
    }
    return 0;
}

1004

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
#define ll long long

inline char nc()
{
    static char buf[100000],*p1=buf,*p2=buf;
    if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
    return *p1++;
}

inline void read(int &x)
{
    char c=nc(),b=1;
    for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
    for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

int n,m;
int sum[2005];
double f[2005];

inline double Log(int x){
    return log((double)x)/log(2.0);
}

int main()
{
    int Q,a;
    read(Q);
    while (Q--)
    {
        cl(sum); cl(f);
        read(m); read(n);
        for (int i=1;i<=n;i++) read(a),sum[++a]=1;
        for (int i=1;i<=m;i++) sum[i]+=sum[i-1];
        for (int i=1;i<=m;i++)
            for (int j=i-1;j>=0;j--)
            {
                if (sum[i]-sum[j]>1) break;
                if (sum[i]-sum[j]<1) continue;
                f[i]=max(f[i],f[j]+Log(i-j));
            }
        printf("%I64d\n",(ll)(f[m]*1000000.0));
    }
    return 0;
}

1005
在线打法

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;
struct Rec
{
   int a,b,c;
   inline friend bool operator !=(Rec a,Rec b)
   {return (a.a^b.a)|(a.b^b.b)|(a.c^b.c);}
};
const
   int MaxHash=213133;
inline int Calc(Rec Key)
{
    return ((Key.a*3+Key.b*76721+Key.c*23)%MaxHash+MaxHash)%MaxHash;
}
struct Hash
{
   Rec Key;
   int Latest;
   Hash*next;
}*Table[MaxHash];
Hash Hash_Cache[MaxHash];
int Hash_Tot;
inline Hash*New_Hash(){return Hash_Cache+Hash_Tot++;}
Hash *Ans;

bool find(Rec Key,Hash*Cur)
{
    if(!Cur)return false;
    if(Cur->Key!=Key)return find(Key,Cur->next);
    Ans=Cur;return true;
}

inline void insert(Rec Key,int place,int time)
{
   Hash*tp=New_Hash();
   tp->next=Table[place];
   Table[place]=tp;
   tp->Latest=time;
   tp->Key=Key;
}

struct Seg
{
    Seg *lc,*rc;
    int l,r;
    int data;
}*Root[200001];

Seg Seg_Cache[5000000];
int Seg_Tot;
inline Seg*New_Seg()
{return Seg_Cache+Seg_Tot++;}
int Query(Seg*Cur,int L)
{
   if(!Cur)return 0;
   if(Cur->r<L)return 0;
   else if(Cur->l>=L)return Cur->data; 
   else 
     {
        int res=0;
        res=Query(Cur->lc,L);
        res+=Query(Cur->rc,L);
        return res;
     }
}

Seg*Modify(Seg*Cur,int L)
{
    Seg*Ne=New_Seg(); 
    *Ne=*Cur;
    Ne->data++;
     if(Cur->l^Cur->r)
     {
      int Mid=Cur->l+Cur->r>>1;
      if(Mid<L)
        Ne->rc=Modify(Ne->rc,L);
      else
        Ne->lc=Modify(Ne->lc,L);
     }
   return Ne;
}
Seg*Build(int L,int R)
{
    Seg*Ne=New_Seg(); 
    Ne->l=L;Ne->r=R;
    Ne->lc=Ne->rc=NULL;
    Ne->data=0;
     if(L^R)
     {
        int Mid=L+R>>1;
        Ne->rc=Build(Mid+1,R);
        Ne->lc=Build(L,Mid);
     }
   return Ne;
}
int n,Q;
int A[200001];
char c;
inline void read(int &a)
{
  a=0;do c=getchar();while(c<'0'||c>'9');
  while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();

}
int Val[200001];
int main()
{
    Rec tp;
     int pl,T;
    read(T);
    while(T--)
  {  
    Hash_Tot=Seg_Tot=0;
    memset(Table,0,sizeof(Table));
    read(n); 
    Root[1]=Root[0]=Root[2]=Build(1,n);
    for(int i=1;i<=n;i++)
     read(A[i]);
    for(int i=3;i<=n;i++)  
     {
         tp.a=A[i-2],tp.b=A[i-1],tp.c=A[i];
          Val[i]=0;
        if(tp.a<=tp.b&&tp.b<=tp.c)
         if(!find(tp,Table[pl=Calc(tp)]))
              insert(tp,pl,i),Root[i]=Modify(Root[i-1],1);
         else
           {
              Root[i]=Modify(Root[i-1],Ans->Latest);
              Ans->Latest=i;       
          }
        else Val[i]=-1,Root[i]=Root[i-1];   
       Val[i]=Val[i-1]+Val[i]+1;
      }
   read(Q);
    int L,R;
    while(Q--)
    {
       read(L),read(R);
       if(R-L<=1)
           {puts("0");continue;}
       int  ans=Query(Root[R],L+2);   
       ans=Val[R]-Val[L+1]-ans; 
        printf("%d\n",ans);
   }
 }
    getchar();
    getchar();
    getchar();
    getchar();
    getchar();
    getchar();
    getchar();
    getchar();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值