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