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初始化写到了循环里面, 剁手,,,,,,,
明天第一场多校训练, 加油啦。
浙公网安备 33010602011771号