ZOJ Monthly, June 2012

ZOJ Monthly, June 2012

http://acm.zju.edu.cn/onlinejudge/showContestProblems.do?contestId=338


B题   我用的是二分 + 树状数组 ,x&(-x) 写成了 x&(-x)弄了半天

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=100010;
#define lowbit(x) x&(-x)

ll tab[maxn],num[maxn],op[maxn];
int Max,tot;
char ord[maxn][10];
int cnt[maxn];

int bin1(ll key)
{
    int l=1,r=Max,mid;
    while(l<=r)
    {
        mid=(l+r)>>1;
        if(tab[mid]==key) return mid;
        else if(tab[mid] > key) r=mid-1;
        else l=mid+1;
    }
}
void insert(int pos,int d)
{
    for(int i=pos;i<=Max;i+=lowbit(i))
      num[i]+=d;
}
int query(int pos)
{
    int sum=0;
    for(int i=pos;i>0;i-=lowbit(i))
      sum+=num[i];
    return sum;
}
long long bin2(int s)
{
    int l=1,r=Max,mid,ans=Max;
    while(l<=r)
    {
        mid=(l+r)>>1;
        int tmp=query(mid);
        if(tmp>=s)
        {
            ans=mid,r=mid-1;
        }
        else  l=mid+1;
    }
    return tab[ans];
}
int main()
{
    int ca,n,k;
    scanf("%d",&ca);

    while(ca--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%s %lld",ord[i],&op[i]);
            tab[i+1]=op[i];
        }
        sort(tab+1,tab+n+1);
        Max=1;
        for(int i=2;i<=n;i++)
         if(tab[i]!=tab[i-1]) tab[++Max]=tab[i];
        memset(num,0,sizeof(num));
        memset(cnt,0,sizeof(cnt));
        tot=0;
        //cout<< Max <<endl;
        for(int i=0;i<n;i++)
        {
            int pos=bin1(op[i]);
            //cout<<"bug" << pos <<" "<< query(pos) <<endl;
            if(ord[i][0]=='a')
            {
                tot++;
                insert(pos,1);
                cnt[pos]++;
                if(tot%2)
                {
                    printf("%lld\n",bin2(tot/2+1));
                }
                else
                {
                    long long a=bin2(tot/2),b=bin2(tot/2+1);
                    //cout<< a <<" "<< b<< " " << query(3)<<endl;
                    if(((a+b)%2+2)%2==0) printf("%lld\n",(a+b)/2);
                    else printf("%.1lf\n",(a+b)*1.0/2);
                }
            }
            else
            {
                int now=query(pos),pre=query(pos-1);
                //cout<< pre <<" "<<now<<endl;
                if(cnt[pos]==0) puts("Wrong!");
                else
                {
                    tot--;
                    insert(pos,-1);
                    cnt[pos]--;
                    if(tot==0) puts("Empty!");
                    else
                    {
                        if(tot%2)
                        {
                            printf("%lld\n",bin2(tot/2+1));
                        }
                        else
                        {
                                long long a=bin2(tot/2),b=bin2(tot/2+1);

                                if(((a+b)%2+2)%2==0) printf("%lld\n",(a+b)/2);
                                else printf("%.1lf\n",(a+b)*1.0/2);
                        }
                    }
                }
            }
        }
    }
    return 0;
}
/*
8
add 1
add 1
add 1
add 3
add 3
add 4
add 2
remove 2
*/


J题  这个题很简单 ,很常见的状态压缩dp,d[state][node] 表示遍历了state 状态 到达node 节点所花费的最短时间

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;
const int INF=100000000;
int n,m,T;
int value[10],start,end,dist[10][10];
int ans;
int dp[1024][11];

void floyed()
{
    /* for(int i=0;i<n;i++)
     for(int j=0;j<n;j++)
        dist[i][j]=map[i][j];*/
     for(int i=0;i<n;i++)
     for(int j=0;j<n;j++)
     for(int k=0;k<n;k++)
     {
         dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);
     }
}

int main()
{
    int a,b,c;
    while(scanf("%d%d%d",&n,&m,&T)==3)
    {
        scanf("%d%d",&start,&end);
        for(int i=0;i<n;i++) scanf("%d",&value[i]);
        for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
          dist[i][j]=INF;
        for(int i=0;i<m;i++)
        {
            scanf("%d %d %d",&a,&b,&c);
            if(dist[a][b]>c) dist[a][b]=dist[b][a]=c;
        }
        for(int i=0;i<n;i++) dist[i][i]=0;
        floyed();
        ans=0;
        for(int j=0;j<(1<<n);j++)
        for(int i=0;i<n;i++)
          dp[j][i]=INF;
        dp[1<<start][start]=0;
        int limit=1<<n;
        for(int i=0;i<limit;i++)
        for(int j=0;j<n;j++)
          if(dp[i][j]<=T)
          {
              for(int k=0;k<n;k++)
                dp[i|(1<<k)][k]=min(dp[i|(1<<k)][k],dp[i][j]+dist[j][k]);
          }
         //int ans
         for(int i=0;i<limit;i++)
          if(dp[i][end]<=T)
          {
              int sum=0;
              for(int j=0;j<n;j++)
                if(i&(1<<j)) sum+=value[j];
              if(ans<sum)  ans=sum;
          }
          printf("%d\n",ans);
    }
    return 0;
}

最蛋疼的就是K了,浪费了我这么多时间,还没有做出来,思路我想出来了,就是把题意理解的错误,0 ≤ s < 2^63, 2 ≤ k ≤ 62 ,这个s如果用十进制的组多2^63,我还以为long long 也会超,都没敢再做;

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

using namespace std;
typedef unsigned long long ll;
const ll inf=1LL<<63;

int a[110];
vector<pair<int,int> > e[110];
ll sum[110];

int main()
{
    ll s;
    char str[110];
    int k;
   for(int i=2;i<=62;i++){
        if(a[i]==0){
            e[i].push_back(make_pair(i,1));
            for(int j=i*2;j<=62;j+=i){
                a[j]=1;
                int t=j,cnt=0;
                while(t%i==0){
                    t/=i;
                    cnt++;
                }
                e[j].push_back(make_pair(i,cnt));
            }
        }
    }
    //for(int i=0;i<e[62].size();i++)
    //      cout<< e[62][i].first<<" "<<e[62][i].second<<endl;
    while(cin>>str>>k)
    {
        int len=strlen(str);
        s=0;int p;
        for(int i=0;i<len;i++){
            if('0'<=str[i]&&str[i]<='9')
                p=str[i]-'0';
            else if('A'<=str[i]&&str[i]<='Z')
                p=str[i]-'A'+10;
            else if('a'<=str[i]&&str[i]<='z')
                p=str[i]-'a'+36;
            s=s*k+p;
        }
        //cout<< s <<endl;
        ll ans=inf;
        for(int i=0;i<e[k].size();i++)
        {
            int p=e[k][i].first;
            ll N=s,cnt=0;
            while(N)
            {
                cnt+=N/p;
                N/=p;
            }
            ans=min(ans,cnt/e[k][i].second);
        }
        cout<< ans <<endl;
    }
    return 0;
}

D题 还有没有ac,不知道怎么错了,先贴出了以后再看;
#include <iostream>
#include <cstdio>

using namespace std;
const int maxn=510;

int n,m;
double matrix[maxn][maxn],sum1[maxn][maxn],sum2[maxn][maxn];
double heig[maxn][maxn],heigh[maxn][maxn];
int que[maxn];

int main()
{
    int Q,a,b,ca=1;
    while(scanf("%d %d",&n,&m)==2)
    {
        for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
        {
           scanf("%lf",&matrix[i][j]);
           sum1[i][j]=sum2[i][j]=0;
        }
        for(int i=0;i<n;i++)
        {
            double tot=0;
            for(int j=0;j<m;j++)
            {
               tot+=matrix[i][j];
               sum1[i][j]= (i==0?0:sum1[i-1][j])+tot;
            }
        }
        for(int i=0;i<n;i++)
        {
            double tot=0;
            for(int j=0;j<m;j++)
            {
               tot+=matrix[i][j]*matrix[i][j];
               sum2[i][j]=(i==0?0:sum2[i-1][j])+tot;
            }
        }
       // cout<<sum1[1][1]<<" "<<sum2[2][0]<<endl;
        printf("Case %d:\n",ca++);
        scanf("%d",&Q);
        double ans=99999999;
        int sx,sy;
        while(Q--)
        {
            scanf("%d %d",&a,&b);
            ans=99999999;
            for(int i=0;i<n;i++)
            {
                int l=0,r=-1;
                for(int j=0;j<m;j++)
                {
                    while(l<=r&&matrix[i][que[r]] < matrix[i][j]) r--;
                    que[++r]=j;
                    if(j>=b-1) heig[i][j-b+1]=matrix[i][que[l]];
                    if(r-l+1>=b) l++;
                }
            }
            //cout<< heig[1][1] <<endl;
            for(int i=0;i<m;i++)
            {
                int l=0,r=-1;
                for(int j=0;j<n;j++)
                {
                    while(l<=r&&heig[que[r]][i] < heig[j][i]) r--;
                    que[++r]=j;
                    if(j>=a-1) heigh[j-a+1][i]=heig[que[l]][i];
                    if(r-l+1>=a) l++;
                }
            }
            //cout<< heigh[2][3] <<endl;
            for(int i=0;i<=n-a;i++)
            for(int j=0;j<=m-b;j++)
             {
                 double tmp1=(sum2[i+a-1][j+b-1]- (j==0?0:sum2[i+a-1][j-1]) - (i==0?0:sum2[i-1][j+b-1]) + ((i==0||j==0)?0:sum2[i-1][j-1]) -heigh[i][j]*heigh[i][j])/(a*b-1);
                 double tmp2=(sum1[i+a-1][j+b-1]- (j==0?0:sum1[i+a-1][j-1]) - (i==0?0:sum1[i-1][j+b-1]) + ((i==0||j==0)?0:sum1[i-1][j-1])-heigh[i][j])/(a*b-1);
                 tmp2*=tmp2;
                 if(tmp1-tmp2 < ans)
                 {
                     ans=tmp1-tmp2;
                     sx=i,sy=j;
                 }
                 else if(tmp1-tmp2 == ans&&sx>i)
                 {
                    // ans=tmp1-tmp2;
                     sx=i,sy=j;
                 }
                 else if(tmp1-tmp2 == ans&&sx==i&&sy>j)
                 {
                     //ans=tmp1-tmp2;
                     sx=i,sy=j;
                 }
             }
             printf("(%d, %d), %.2lf\n",sx+1,sy+1,ans);
        }
    }
    return 0;
}
D 题终于知道错在哪里了,一个傻逼错误wa的我半死不活了,bug半天也没看出来,跟ac程序对拍才发现
  if(r-l+1>=b) l++;
写错了,看来模版题还是要多敲呀多记呀


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值