zsacm20120226省赛前个人赛第1场(结题报告)

1.http://acm.hdu.edu.cn/showproblem.php?pid=1754

之前做过的线段树,单点更新,难度不大,连标记下传也不用了,用了之前学习到的代码,就是代码记忆不够熟练,中间有的地方总是写错,简直浪费时间。

#include <stdio.h>
#include <algorithm>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define maxn 200001
int MAX[maxn<<2];
int max(int a,int b)
{
    return a>b?a:b;
}
void pushup(int rt)
{
    MAX[rt]=max(MAX[rt<<1],MAX[rt<<1|1]);
}
void build(int l,int r,int rt)
{
    if(l==r)
    {
        scanf("%d",&MAX[rt]);
        return ;
    }
    int mid=(l+r)>>1;
    build(lson);
    build(rson);
    pushup(rt);
}
void update(int p,int sc,int l,int r,int rt)
{
    if(l==r)
    {
        MAX[rt]=sc;
        return ;
    }
    int mid=(l+r)>>1;
    if(p<=mid) update(p,sc,lson);
    else update(p,sc,rson);
    pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        return MAX[rt];
    }
    int mid=(l+r)>>1;
    int ret=0;
    if(L<=mid) 
        ret=max(ret,query(L,R,lson));
    if(R>mid) 
        ret=max(ret,query(L,R,rson));
    return ret;
}
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        build(1,n,1);
        while(m--)
        {
            char st[2];
            int a,b;
            scanf("%s%d%d",st,&a,&b);
            if(st[0]=='Q')
                printf("%d\n",query(a,b,1,n,1));
            else
                update(a,b,1,n,1);
        }
    }
    return 0;
}

 

2.http://acm.hdu.edu.cn/showproblem.php?pid=3333

一看名字就知道又是一个树的题目,解释:图灵树。

题意很简单,求给定数组中一段区间不同数字的和。刚开始想到大数据要离散化,线段树求值,可是总是怎么多写不出来。看了网上的报告瞬间觉得无语,这么简单。思路没错,果然还是代码能力的问题。

思路:假定原始数组是 a = 1,1,4.去重之后是 b = 1,4.
那么建立一个 c 数组,保存 a 中的元素在 b 中的下标。c = 0,0,2.
对 c 建立线段树查询即可。

#include<iostream>
#include<cmath>
#include<algorithm>

#define MAXN 100001
using namespace std;


int n;
int a[MAXN];
__int64 c[MAXN];
int pre[MAXN];
int next[MAXN];
__int64 res[MAXN];

struct node
{
    int s,e;
    int pos;
}q[100010];


int lowbit(int x)
{
    return x & (x ^ (x-1));
}

__int64 sum(int x)
{
    __int64 sum = 0;
    while(x > 0)
    {
        sum += c[x];
        x -= lowbit(x);
    }
    return sum;
}

void modify(int i,int x,int n)
{
    while(i <= n)
    {
        c[i] += x;
        i += lowbit(i);
    }
    
}


bool cmp(node a,node b)
{
    if (a.s == b.s)
        return a.e < b.e;
    return a.s < b.s;
}

int main()
{
    int t,m;
    while(scanf("%d",&t)!=EOF)
    {
        while(t--)
        {
            memset(a,0,sizeof(a));
            memset(c,0,sizeof(c));
            scanf("%d",&n);
            for(int i = 1;i <= n;++i)
                scanf("%d",&a[i]);
            for(int i = n;i >= 1;--i)
            {
                pre[i] = -1;
                for(int j = i-1;j >= 1;--j)
                    if (a[i] == a[j])
                    {
                        pre[i] = j;
                        break;
                    }
            }//计算next
            for(int i = 1;i <= n;++i)
            {
                next[i] = n+1;
                for(int j = i + 1;j <= n;++j)
                    if (a[i] == a[j])
                    {
                        next[i] = j;
                        break;
                    }
            }
            for(int i = 1;i <= n;++i)
            {
                if (pre[i] == -1)
                    modify(i,a[i],n);
                else
                    modify(i,0,n);
            }
            scanf("%d",&m);
            for(int i = 0;i < m;++i)
            {
                scanf("%d%d",&q[i].s,&q[i].e);
                q[i].pos = i;
            }
            
            sort(q,q+m,cmp);
            int index = 1;
            for(int i = 0;i < m;++i)
            {
                for(int j = index;j < q[i].s;++j)
                {
                    
                    

                    modify(j,-a[j],n);
                    
                    pre[next[j]] = -1;
                    modify(next[j],a[next[j]],n);
                    
                }
                index = q[i].s;
                __int64 ans;
                if (q[i].s == 1)
                {
                    ans = sum(q[i].e);
                //    printf("ans:%I64d\n",ans);
                }
                else
                {
                    //cout<<sum(q[i].e)<<' '<<sum(q[i].s - 1)<<endl;
                    ans = sum(q[i].e) - sum(q[i].s - 1);
                }
                res[q[i].pos] = ans;
            }
            for(int i = 0;i < m;++i)
                printf("%I64d\n",res[i]);
        }
    }
    return 0;
}

 

3.http://acm.hdu.edu.cn/showproblem.php?pid=3342

这道题主要就是判断是否能拓扑排序(就是不能构成环),能的话就输出YES,不能侧输出NO。题意耐心看就出来了。

 

#include<iostream>
using namespace std;
#define maxn 105
int map[maxn][maxn];
int degree[maxn];
int n,m;
int top;
int f[maxn];
void toposort()
{      int i,j,k;
       for(i=0;i<n;i++)
       {    for(j=0;j<n;j++)
            {    if(degree[j]==0)
                 {    degree[j]--;
                      top++;
                      for(k=0;k<n;k++)
                      {   if(map[j][k]) degree[k]--;
                      }
                      break;
                  }
            }
        }
}
          
int main()
{   
     int i,j,k;
     while(cin>>n>>m)
     {     if(n==0&&m==0) break;
           memset(map,0,sizeof(map));
           memset(degree,0,sizeof(degree));
           int a,b;
           while(m--)
           {    cin>>a>>b;
                if(map[a][b]==0)
                {   map[a][b]=1;
                    degree[b]++;
                }
           }
           top=0;
           toposort();
           if(top==n) cout<<"YES"<<endl;
           else cout<<"NO"<<endl;
      }
return 0;
}

 

 4.http://acm.hdu.edu.cn/showproblem.php?pid=1284

怎么说,就是数学题,逻辑考一考,难度不是很大,转来转去的。只需要计算出可以换多少3分的和多少2分的就可以了。

#include <stdio.h>
int main ()
{
 int n,s,i;
 while (scanf("%d",&n)!=EOF)
 {
      s=n/3+1;//计算3分的
      for (i=0;i<=n/3;i++)
       s+=(n-3*i)/2;//计算2分的 不过因为已经算过3分的 所以那一部分要先减掉
      printf ("%d\n",s);
 }
 return 0;
}

 

5.http://acm.hdu.edu.cn/showproblem.php?pid=2053

简单题,看题目就好。水过的。

#include <iostream>
using namespace std;
int main()
{
    int i,c,n;
    while(scanf("%d",&n)!=EOF)
    {
        for(i=1,c=0;i<=n;i++)
        {
            if(n%i==0)
                c++;
        }
        printf("%d\n",c&1);
    }
    
    return 0;
}

6.http://acm.hdu.edu.cn/showproblem.php?pid=2617

此题用一般的遇到一个h就向下查找会超时,即使是把那些不是h,a,p,y的字符去掉重新组成一个字符串,再用此方法也会超时。不过做到最好发现还是一个个查找就对了,就是自己写聪明点。

 

#include<cstdio>
#include<iostream>
using namespace std;
#include<cstring>
int main()
{   
 char s[10001]; 
 int h,a,p1,p2,y,i;  
 while(gets(s)!=NULL)    
 {       
  h=a=p1=p2=y=0;        
  for(i=0;s[i]!='\0';i++)   
  {            
     if(s[i]=='h') h++;
     if(s[i]=='a')
     {
      if(h) {h--;a++;}
     }
     else if(s[i]=='p')
     {
      if(p1) {p1--;p2++;}
      else if(a) {p1++;a--;}
     }
     else if(s[i]=='y')
     {
      if(p2) {y++;p2--;}
     }
  }
  cout<<y<<endl;
 }
 return 0;
}

 

 

7.http://acm.hdu.edu.cn/showproblem.php?pid=4151

水题,打表,二分暴力查找。

#include<stdio.h>
#include<string.h>
int a[1000000];
int main()
{
    int b[10];
    int i,j,n,k=1,low,high,mid;
    for(i=1;i<=10000000;i++)
    {
        memset(b,0,sizeof(b));
        j=i;
        while(j)
        {
            if(b[j%10]!=1)
            {
                b[j%10]=1;
                j/=10;}
            else break;
        }
        if(j==0)
            a[k++]=i;
    }
    while(scanf("%d",&n)!=EOF)
    {
            low=1;
            high=k-1;
            while(low<=high)
            {
                mid=(low+high)/2;
                if(a[mid]>=n)
                    high=mid-1;
                else low=mid+1;
            }
            printf("%d\n",high);
    }
    return 0;
}

 

8.http://acm.hdu.edu.cn/showproblem.php?pid=3764

水题,注意题目说的返回的时候没有充电站,所以距离差要小于100.

#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
int lu[1423000];
int main()
{

    int n,m,i,j;
    int flag;
    while(~scanf("%d",&n),n)
    {
        flag=1;
        for(i=0;i<n;i++)
            scanf("%d",&lu[i]);
        sort(lu,lu+n);
        for(i=1;i<n;i++)
            if(lu[i]-lu[i-1]>200)
            {
                flag=0;
                break;
            }
            if(flag&&1422-lu[n-1]>100)
                flag=0;
            if(flag)
                puts("POSSIBLE");
            else
                puts("IMPOSSIBLE");
            
    }
    return 0;
}

 

9.http://acm.hdu.edu.cn/showproblem.php?pid=4156

水题,判断是不是勾股三角形。

#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
int main()
{
    int a,b,c;
    int num[3];
    while(~scanf("%d%d%d",&num[0],&num[1],&num[2])&&(num[0]&&num[1]&&num[2]))
    {
         sort(num,num+3);
         if(num[0]*num[0]+num[1]*num[1]==num[2]*num[2])
             puts("right");
         else
             puts("wrong");
    }
    return 0;
}

 

 

总结:

老师完美的出题,大大的感受了AC的快感。以后就没这么简单了.

 

 

 

posted @ 2012-02-28 16:39  Lxsec  阅读(214)  评论(0编辑  收藏  举报