WHUST individual contest #1 总结

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=83216#overview

今天是华科和武大进行合训第一天, bj女票来了武汉,so,他和女票出去浪了。 我和小东把他留下的锅给填上。

今天题目跨度有点打, 中间vj出了点问题。 不过到了中后期,, 真是有点坐不住了, 题目不会做。。

 

A. HDU 4005 没有做出来, 是个图论题目。 事后补上

 

B. HDU4008 LCA和DFS序的题目,有点难想。

 

C.HDU4029 字符串题目 等bj大大浪回来了去看看

 

D.HDU4052 线段树+扫描线 这道题好巧妙。

   题意:给一个W*H的矩阵,给N个小矩阵坐标为x1,y1,x2,y2. 然后让我们去放置一个1*m或者m*1的矩阵, 问有多少种放置方法。

   分横竖两种情况进行处理,可以先把不能放置的地方给处理出来, 然后进行面积并, 总面积减去不能放置的面积,就是可以放置的地方。

   第一个就是对于横着的情况, 假设坐标是x1,y1,x2,y2 那么x1,y1,x2+m-1,y2,这些地方是不能放置的, 纵向 x1,y1,x2,y2+m-1, 还有一个重要的地方就是处理边界,假设m不为1的话, 1,1一定不可以放置吧? 于是我们就可以在矩形下方和矩形右方搞两个小矩阵,把这些不能放置的地方去除。

  代码:

   

#include<bits/stdc++.h>
#define inf 0x7f7f7f7f
#define LL long long

using namespace std;

const int N=100010;

struct Line{
    int x,y1,y2;
    int flag;
    Line(){};
    Line(int xx, int yy1, int yy2, int fflag):x(xx),y1(yy1),y2(yy2),flag(fflag){};
    bool operator <(const Line &cmp) const{
        return x<cmp.x;
    }
}line[2*N];
struct Tree{
    int l,r,c;
    int cover,lf,rf;
}tree[4*N];
int y[2*N];
int x1[N],yy1[N],x2[N],y2[N];

void Build(int t, int l, int r)
{
    tree[t].l=l;
    tree[t].r=r;
    tree[t].cover=tree[t].c=0;
    tree[t].lf=y[l];
    tree[t].rf=y[r];
    if (l+1==r)
        return;
    int m=(l+r)/2;
    Build(t*2,l,m);
    Build(t*2+1,m,r);
}

void Pushup(int t)
{
    if (tree[t].c>0){
        tree[t].cover=tree[t].rf-tree[t].lf;
    }
    else
    if (tree[t].l+1==tree[t].r)
        tree[t].cover=0;
    else
        tree[t].cover=tree[2*t].cover+tree[2*t+1].cover;
}

void Update(int t, int l, int r, int flag)
{
    if (l==tree[t].lf && r==tree[t].rf){
        tree[t].c+=flag;
        Pushup(t);
        return;
    }
    if (r<=tree[2*t].rf)
        Update(2*t,l,r,flag);
    else
    if (l>=tree[2*t+1].lf)
        Update(2*t+1,l,r,flag);
    else{
        int m=(tree[t].l+tree[t].r)/2;
        Update(2*t,l,y[m],flag);
        Update(2*t+1,y[m],r,flag);
    }
    Pushup(t);
}

LL work(int n)
{
    LL ans=0;
    int k;
    sort(line+1,line+1+n);
    sort(y+1,y+1+n);
    k=unique(y+1,y+1+n)-y-1;

    Build(1,1,k);
    for (int i=1;i<=n;i++){
        ans+=(LL)tree[1].cover*(LL)(line[i].x-line[i-1].x);
        Update(1,line[i].y1,line[i].y2,line[i].flag);
    }
    return ans;
}

int main()
{
    int n,m;
    int W,H;
    LL ans,w,h;
    while (scanf("%d%d%d%d",&W,&H,&n,&m)!=EOF)
    {
        w=W;
        h=H;
        ans=0;
        for (int i=1;i<=n;i++)
        {
            scanf("%d%d%d%d",&x1[i],&yy1[i],&x2[i],&y2[i]);
            x1[i]--;
            yy1[i]--;
        }

        for (int i=1;i<=n;i++)
        {
            line[2*i-1]=Line(x1[i],yy1[i],y2[i],1);
            line[2*i]=Line(min(W,x2[i]+m-1),yy1[i],y2[i],-1);
            y[2*i-1]=yy1[i];
            y[2*i]=y2[i];
        }
        if (m!=1)
        {
            line[2*n+1]=Line(0,0,H,1);
            line[2*n+2]=Line(min(W,m-1),0,H,-1);
            y[2*n+1]=0;
            y[2*n+2]=H;
        }
        if (m!=1) ans=w*h-work(n*2+2);
        else
        {
            if (n==0) ans=w*h; else ans=w*h-work(n*2);
        }

        for (int i=1;i<=n;i++)
        {
            line[2*i-1]=Line(x1[i],yy1[i],min(H,y2[i]+m-1),1);
            line[2*i]=Line(x2[i],yy1[i],min(H,y2[i]+m-1),-1);
            y[2*i-1]=yy1[i];
            y[2*i]=min(H,y2[i]+m-1);
        }
        if (m!=1)
        {
            line[2*n+1]=Line(0,0,min(H,m-1),1);
            line[2*n+2]=Line(W,0,min(H,m-1),-1);
            y[2*n+1]=0;
            y[2*n+2]=min(H,m-1);
        }
        //cout<<ans<<endl;
        if (m!=1) ans=ans+w*h-work(n*2+2);
        else
        {
            if (n==0) ans=ans+w*h; else ans=ans+w*h-work(n*2);
        }
        if (m==1) ans=ans/2;
        cout<<ans<<endl;
    }
    return 0;
}

 G HDU4104

    给N个数,问不能组成的最小值是多少。

    这个题先从小到大排序,逐渐累加, 如果当前累加的和+1比当前的值还小的话,那么sum+1这个值就一定取不到。 

  

#include<bits/stdc++.h>

using namespace std;

int p[1010];

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        int sum=0;
        for (int i=0;i<n;i++) scanf("%d",&p[i]);
        sort(p,p+n);
        int ans=0;
        for (int i=0;i<n;i++)
        {
            if (sum+1<p[i]&&ans==0)
            {
                ans=sum+1;
            }
            sum=sum+p[i];
        }
        if (ans==0) ans=sum+1;
        cout<<ans<<endl;
    }
    return 0;
}

  后边的题目比较简单, 就不一一总结了。 

      今天的小插曲, K题手抖, 把总体更新的ans初始化写到了循环里面, 剁手,,,,,,,

 

      明天第一场多校训练, 加油啦。

posted on 2015-07-20 19:30  wzb_hust  阅读(371)  评论(0编辑  收藏  举报

导航