HHU ACM 综合训练2
来源:互联网 发布:淘宝的交易流程 编辑:程序博客网 时间:2024/05/01 22:12
本次综合训练主要是2013年的大连online的题目,有难有易,其中题意不太清楚和要求非常高的题目就直接剔除了。这样题数少了,于是又加了2题2016年大连online的我觉得挺不错的题目。后来发现知识点有点重叠,不过一套比赛本来就是这样。
Find the maximum
题意:给出
题解:做这题首先要知道
其中
【考虑到大家提交的很多代码都是打表,这里我写的比较详细
明显地:
1.
2.
所以,只需要把最小的那些质数乘起来,就能得到满足条件的
为了增加(编程)难度,这题又加入了高精度,套用模板,代码如下:
#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int MAX=1000000;int pr[100000],pt=0;bool f[MAX];char s[110];struct BigInt { const static int mod = 10000; const static int DLEN = 4; int a[100],len; BigInt() { memset(a,0,sizeof(a)); len = 1; } BigInt(int v) { memset(a,0,sizeof(a)); len = 0; do { a[len++] = v%mod; v /= mod; } while(v); } BigInt(const char s[]) { memset(a,0,sizeof(a)); int L = strlen(s); len = L/DLEN; if(L%DLEN)len++; int index = 0; for(int i = L-1; i >= 0; i -= DLEN) { int t = 0; int k = i - DLEN + 1; if(k < 0)k = 0; for(int j = k; j <= i; j++) t = t*10 + s[j] - '0'; a[index++] = t; } } BigInt operator +(const BigInt &b)const { BigInt res; res.len = max(len,b.len); for(int i = 0; i <= res.len; i++) res.a[i] = 0; for(int i = 0; i < res.len; i++) { res.a[i] += ((i < len)?a[i]:0)+((i < b.len)?b.a[i]:0); res.a[i+1] += res.a[i]/mod; res.a[i] %= mod; } if(res.a[res.len] > 0)res.len++; return res; } BigInt operator *(const BigInt &b)const { BigInt res; for(int i = 0; i < len; i++) { int up = 0; for(int j = 0; j < b.len; j++) { int temp = a[i]*b.a[j] + res.a[i+j] + up; res.a[i+j] = temp%mod; up = temp/mod; } if(up != 0) res.a[i + b.len] = up; } res.len = len + b.len; while(res.a[res.len - 1] == 0 &&res.len > 1)res.len--; return res; } bool operator >(const BigInt &b)const { if (len==b.len) { int k=len-1; while (k&&a[k]==b.a[k]) k--; if (k<0) return false; return a[k]>b.a[k]; } return len>b.len; } void output() { printf("%d",a[len-1]); for(int i = len-2; i >=0 ; i--) printf("%04d",a[i]); printf("\n"); }};void init_pr(){ for (int i=2;i<MAX;i++) { if (!f[i]) pr[++pt]=i; for (int j=1;j<=pt;j++) { if (i*pr[j]>=MAX) break; f[i*pr[j]]=1; if (i%pr[j]==0) break; } }}int main(){ init_pr(); int T; scanf("%d",&T); while (T--) { scanf("%s",s); BigInt n(s); BigInt a(1),b(1); for (int i=1;i<=pt;i++) { BigInt tmp(pr[i]); b=a*tmp; if (b>n) break; a=b; } a.output(); } return 0;}
The Frog’s Games
题意:青蛙要跳过一条长为
题解:可以发现,最后的答案具有单调性,即,若跳跃能力
由此,使用二分答案可以解决,代码如下:
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N=500010;int a[N];int L,n,m;bool check(int l){ int cnt=0,pre=0; for (int i=1;i<=n+1;) { while (pre+l>=a[i]&&i<=n+1) i++; pre=a[i-1]; if (++cnt>m) return false; } return true;}int bs(int l,int r){ while (l<r) { int m=(l+r)>>1; if (check(m)) r=m; else l=m+1; } return l;}int main(){ while (scanf("%d%d%d",&L,&n,&m)!=EOF) { for (int i=1;i<=n;i++) scanf("%d",&a[i]); sort(a+1,a+1+n); int l=L,r=L;a[n+1]=L; for (int i=1;i<=n+1;i++) l=min(a[i]-a[i-1],l); printf("%d\n",bs(l,r)); } return 0;}
Different GCD Subarray Query
题意:给出
题解:做这题首先要知道一个结论,值为
其次还需要知道一个技巧,如何统计一个区间内不同的数。对于一个右端点
这样把所有询问离线并排序以后,就可以从
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <map>using namespace std;typedef pair<int,int> PII;const int N=100010;const int MAX=1000010;map<int,int> d[2],cur;struct query { int l,r,id; operator < (const query& b) const { return r<b.r; }} q[N];int a[N],ans[N];int c[MAX];int gcd(int a,int b){ if (!b) return a; return gcd(b,a%b);}void ins(int x,int d){ for (;x<MAX;x+=x&(-x)) { c[x]+=d; }}int query(int x){ if (!x) return 0; int res=0; for (;x>0;x-=x&(-x)) { res+=c[x]; } return res;}int main(){ int n,m; while (scanf("%d%d",&n,&m)!=EOF) { d[0].clear(); d[1].clear(); cur.clear(); memset(c,0,sizeof(c)); for (int i=1;i<=n;i++) scanf("%d",&a[i]); for (int i=1;i<=m;i++) { scanf("%d%d",&q[i].l,&q[i].r); q[i].id=i; } sort(q+1,q+1+m); int now=1,pre=0,k=1; for (int i=1;i<=n;i++) { for (map<int,int>::iterator it=d[pre].begin();it!=d[pre].end();it++) { int x=gcd(a[i],it->first); d[now][x]=max(d[now][x],it->second); } d[now][a[i]]=i; for (map<int,int>::iterator it=d[now].begin();it!=d[now].end();it++) { int x=it->first; if (cur.count(x)&&cur[x]<(it->second)) { ins(cur[x],-1); ins(it->second,1); cur[x]=it->second; } else if (!cur.count(x)) { ins(it->second,1); cur[x]=it->second; } } d[pre].clear(); swap(pre,now); for (;k<=m&&q[k].r==i;k++) { ans[q[k].id]=query(q[k].r)-query(q[k].l-1); } } for (int i=1;i<=m;i++) printf("%d\n",ans[i]); } return 0;}
The kth great number
题意:给
题解:一定要认真读题!这道题目的
理解了这一点这就是一道水题,代码如下:
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <queue>using namespace std;int main(){ int n,k; while (scanf("%d%d",&n,&k)!=EOF) { priority_queue< int,vector<int>,greater<int> > Q; while (n--) { char s[5]; scanf("%s",s); if (s[0]=='I') { int x; scanf("%d",&x); Q.push(x); if (Q.size()>k) Q.pop(); } else { printf("%d\n",Q.top()); } } } return 0;}
Dave
题意:在二维平面上给
题解:因为这一题
如果
这个做法听起来很简单,不过由于离散化等原因,很容易写错(WA3 = =),代码如下:
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int N=1010;typedef long long ll;struct point { int x,y,ix,iy; bool operator < (const point& b) { return ix<b.ix; }} p[N];int qx[N],qy[N];ll add[N<<2],sum[N<<2];int n,r,cntx,cnty;void push_up(int rt){ sum[rt]=max(sum[rt<<1],sum[rt<<1|1]);}void push_down(int rt){ if (add[rt]) { add[rt<<1] += add[rt]; add[rt<<1|1] += add[rt]; sum[rt<<1] += add[rt]; sum[rt<<1|1] += add[rt]; add[rt] = 0; }}void update(int L,int R,int d,int l,int r,int rt){ if (L<=l&&r<=R) { add[rt]+=d; sum[rt]+=d; return; } push_down(rt); int m=(l+r)>>1; if (L<=m) update(L,R,d,lson); if (m<R) update(L,R,d,rson); push_up(rt);}ll query(int L,int R,int l,int r,int rt){ if (L<=l&&r<=R) { return sum[rt]; } push_down(rt); int m=(l+r)>>1; ll res=0; if (L<=m) res=max(res,query(L,R,lson)); if (m<R) res=max(res,query(L,R,rson)); return res;}int ins(int k,int d){ int i; for (i=k;i<=n&&p[i].ix==p[k].ix;i++) { int pos=upper_bound(qy+1,qy+cnty+1,p[i].y+r)-qy-1; update(p[i].iy,pos,d,1,cnty,1); } return i;}int main(){ while (scanf("%d%d",&n,&r)!=EOF) { cntx=cnty=0; for (int i=1;i<=n;i++) { scanf("%d%d",&p[i].x,&p[i].y); qx[++cntx]=p[i].x; qy[++cnty]=p[i].y; } sort(qx+1,qx+cntx+1); sort(qy+1,qy+cnty+1); cntx=unique(qx+1,qx+cntx+1)-qx-1; cnty=unique(qy+1,qy+cnty+1)-qy-1; for (int i=1;i<=n;i++) { p[i].ix=lower_bound(qx+1,qx+cntx+1,p[i].x)-qx; p[i].iy=lower_bound(qy+1,qy+cnty+1,p[i].y)-qy; } sort(p+1,p+n+1); memset(sum,0,sizeof(sum)); memset(add,0,sizeof(add)); int ans=0; for (int i=1,k=1;i<=n;) { while (k<=n&&p[k].x-p[i].x<=r) { k=ins(k,1); } ans=max((ll)ans,sum[1]); i=ins(i,-1); } printf("%d\n",ans); } return 0;}
Weak Pair
题意:一棵树的每个节点有一个非负权值,如果
题解:由于树中任意一个节点的祖先都在同一条链上,所以只需要考虑如何快速的求出一条链上的”Weak Pair”。这题有很多解法,我想到的是将祖先都插入到树状数组,那么在
考虑到权值范围很大,要用离散化,并且要注意
【还有一点就是,题目给的是明确的父子关系,但是没有给根,一定要自己找,WA3 = =
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N=1e5+5;const int MAX=2*N;const long long INF=1LL<<33;long long a[N],b[N],A[2*N];int c[MAX];struct edge { int go,next;} eg[2*N];int last[N];bool vis[N];int tot;long long ans;void adde(int x,int y){ eg[++tot].go=y; eg[tot].next=last[x]; last[x]=tot;}void ins(int x,int d){ for (;x<MAX;x+=x&(-x)) { c[x]+=d; }}long long query(int x){ long long res=0; for (;x;x-=x&(-x)) { res+=c[x]; } return res;}void dfs(int x){ ans+=query(b[x]); ins(a[x],1);// printf("%d %d\n",x,ans); for (int i=last[x];i;i=eg[i].next) { dfs(eg[i].go); } ins(a[x],-1);}int main(){ int T,n; long long k; scanf("%d",&T); while (T--) { tot=0; memset(last,0,sizeof(last)); scanf("%d%lld",&n,&k); for (int i=1;i<=n;i++) { scanf("%lld",&a[i]); A[i]=a[i]; if (a[i]==0) { A[n+i]=b[i]=INF; } else { A[n+i]=b[i]=k/a[i]; } } sort(A+1,A+1+n*2); for (int i=1;i<=n;i++) { a[i]=lower_bound(A+1,A+1+2*n,a[i])-A; b[i]=lower_bound(A+1,A+1+2*n,b[i])-A; } memset(vis,0,sizeof(vis)); for (int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); adde(x,y); vis[y]=1; } int i=1; while (i<=n&&vis[i]) i++; ans=0; dfs(i); printf("%lld\n",ans); } return 0;}
- HHU ACM 综合训练2
- HHU ACM综合训练1 Problem A ~ E
- Contest1002 - HHU ACM 综合训练1 E题 Mouse and Parenthesis(线段树+括号匹配)
- Contest1002 - HHU ACM 综合训练1 A题 Kingdom of Black and White(朴素)
- Contest1002 - HHU ACM 综合训练1 C题 Boxes and Balls(找规律)
- Contest1002 - HHU ACM 综合训练1 B题 Friendship of Mouse(朴素算法)
- hhu
- acm训练推荐(2)
- acm训练
- ACM训练
- java文件综合训练
- 结构体综合训练
- java基础 - 综合训练
- Layout组件综合训练
- SQL综合训练
- FJNU-14级MCS-ACM训练#2
- ACM 字符串综合一
- C语言综合研究与高强度程序设计训练 2
- java读书笔记:内部类
- Apache虚拟主机配置
- 单位
- 如何学习KALI
- 虚函数表存放在哪里
- HHU ACM 综合训练2
- WebSocket实现Android客户端之间的简单通讯
- Docker学习笔记 — Docker与OpenStack集成
- Android 6.0 Reboot 流程源代码分析
- 文章标题 HDU 5112- A Curious Matt
- 普通程序员的四年打杂收货
- linux系统下,工作过程的一些习惯总结
- 安卓中PopupWindows的使用
- 40. Combination Sum II