Test on 09/10/2016
1.勇士闯塔
(tower.pas/c/cpp)
【问题描述】
在遥远的东方,有一座膜塔,膜王抓走了公主,并将其囚禁在膜塔的21层,勇士需要闯塔,解救公主。
现在勇士的前方有n个膜怪,每一个膜怪有一个属性值ai,属性值不同的膜怪视为不同种类的膜怪,现在勇士想知道在第qi~qj个膜怪中有多少种不同的膜怪,请你帮忙解决。
【输入格式】
第1行:2个整数n,q,分别表示膜怪数量以及询问数。
第2行:n个整数,表示每个膜怪的属性值。
第3~q+2行:每行2个整数qi,qj.
【输出格式】
共q行,每行一个整数,表示答案。
【输入输出样例1】
tower.in |
tower.out |
6 3 1 2 3 4 3 5 1 2 3 5 2 6 |
2 2 4 |
【输入输出样例2】
tower.in |
tower.out |
10 5 1 3 5 5 3 3 2 5 4 3 3 3 6 7 5 10 3 6 2 6 |
1 2 4 2 2 |
【数据范围】
对于70%的数据,n ≤ 100,q ≤ 1000;
对于100%的数据,n ≤ 3000,q ≤ 200000,1 ≤ a[i] ≤1000;
数据保证qi ≤ qj。
虽然自己没写但是应该是会的,我觉得应该是用一个数组记录下来从1到i所有的膜怪种类数,然后读入询问,s【qj】-s【qi-1】;
然而题解写的吓到我了。
70分的话O(n^2)的简单算法,在回答询问时,调用上一个询问的答案,例如,有一段区间,1、3、1、1、3、2。上一个询问是1~4,答案是ans,现在有一个询问3~5,那么我们只需要计算1、2、5位置的数对答案的贡献,然后处理一下就行了。
100分需要优化到O(nlogn),也就是传说中的莫队算法。我们可以先将数列分成根号n块,如果一个询问的左端点落在第i块,那么这个询问属于第i块,
那么我们就可以按块处理询问,每个块内将询问按右端点排序,然后处理即可。
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 int main() 5 { 6 freopen("tower.in","r",stdin); 7 freopen("tower.out","w",stdout); 8 int n,q,a[3001]; 9 cin>>n>>q; 10 for(int i=1;i<=n;i++) 11 cin>>a[i]; 12 for(int i=1;i<=q;i++) 13 { 14 int x,y,s=0,b[1001]={}; 15 cin>>x>>y; 16 for(int j=x;j<=y;j++) 17 { 18 if(b[a[j]]==0) 19 {b[a[j]]=1;s++;} 20 } 21 cout<<s<<endl; 22 } 23 return 0; 24 }
2.勇士的背包
(bag.pas/c/cpp)
【问题描述】
经过千辛万苦,勇士终于来到了第15层,这是一个特殊的地方——装备库。
这里一共有N件装备,每一个装备有一个价值Pi和重量Wi,当时由于这些装备没有被长者开光,有些装备不能放在一起,否则会引起共鸣,释放洪荒之力,世界毁灭。并且这种共鸣具有专递性,例如,A不能和B放在一起,B不能和C放在一起,则A也不能和C放在一起。
勇士想知道在他的能力范围内,最多能获得多少价值的装备。
【输入格式】
第1行:3个整数N、M、K,N表示装备件数,M表示勇者的最大负重,K表示有K个(断句)装备不能放在一起的关系。
接下来N行:每行2个整数,Pi、Wi,分别表示每件装备的价值和重量。
接下来K行:每行2个整数A、B,表示第A件装备不能和第B件装备放在一起。
【输出格式】
一个整数,表示所能获得的最大价值。
【输入输出样例】
bag.in |
bag.out |
3 10 1
100 1
200 5
10 5
1 2 |
210 |
【数据范围】
对于40%的数据,K=0
对于100%的数据,0≤N,M,K≤1000,0≤Pi≤10000,1 ≤Wi≤ 10,均为整数,A、B不相等
第一眼看着咦,这不是贪心么,嗯是简单的dp,然而dp还没开始搞,这意味着40分我都拿不到手。嗯回来写01背包。
100分的话需要用并查集维护装备间的关系,把不能放在一起的装备放在一个集合中,这样就转化为了集合背包问题。
并查集是什么QAQ 并查集是有关树的,然而看到树就好高端的样子。
不会滚粗。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<cstdlib> 6 #include<algorithm> 7 using namespace std; 8 int n,w,k,len,v[1010],c[1010],f[1010],F[1010],s[1010],a[1010][1010]; 9 inline int read() 10 { 11 int x=0,f=1; char ch=getchar(); 12 while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getchar();} 13 while(isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();} 14 return x*f; 15 } 16 int find(int x) 17 { 18 return f[x]==x?x:f[x]=find(f[x]); 19 } 20 void work(int x) 21 { 22 for(int i=1;i<=len;i++) 23 if(find(x)==a[i][0]) {s[i]++; a[i][s[i]]=x; return;} 24 len++; 25 s[len]=1; 26 a[len][s[len]]=x; 27 a[len][0]=find(x); 28 } 29 int main() 30 { 31 freopen("bag.in","r",stdin); 32 freopen("bag.out","w",stdout); 33 n=read(); w=read(); k=read(); 34 for(int i=1;i<=n;i++) 35 f[i]=i; 36 for(int i=1;i<=n;i++) 37 v[i]=read(),c[i]=read(); 38 for(int i=1;i<=k;i++) 39 { 40 int x=read(),y=read(); 41 x=find(x); y=find(y); 42 if(x!=y) f[x]=y; 43 } 44 for(int i=1;i<=n;i++) 45 work(i); 46 for(int i=1;i<=len;i++) 47 for(int j=w;j>=0;j--) 48 for(int k=1;k<=s[i];k++) 49 if(j-c[a[i][k]]>=0) F[j]=max(F[j],F[j-c[a[i][k]]]+v[a[i][k]]); 50 printf("%d",F[w]); 51 return 0; 52 }
3.勇士斗膜王
(moking.pas/c/cpp)
【问题描述】
“你还是来了!”
“是的,我来了!”
“膜膜膜……”
“不愧是膜王……”
在膜塔的巅峰——21层上,一场惊世对决开始了。
勇士亮出了他的N件法宝,要启动全部的法宝才能击败膜王,但是,启动第i件法宝需要消耗一个法力值不低于Ai且美观程度不低于Bi的魔石,现在勇士有M块魔石,第i块魔石的法力值为Ci,美观程度为Di,勇士想知道为了打败膜王,需要消耗的魔石的法力值的总和最小为多少。
【输入格式】
第1行:2个整数N、M。
接下来N行:每行2个整数Ai,Bi。
接下来M行:每行2个整数Ci,Di。
【输出格式】
一个整数,表示需要消耗的魔石的法力值的总和的最小值。
若无法打败膜王,输出“Failed”。
【输入输出样例1】
moking.in |
moking.out |
2 3 2 7 5 2 4 1 8 8 7 1 |
Failed |
【输入输出样例2】
moking.in |
moking.out |
3 4 1 3 4 7 6 6 5 5 6 4 7 9 9 10 |
21 |
【数据范围】
对于30%的数据,1≤N≤5000,1≤M≤5000
对于100%的数据,1≤N≤100000,0≤M≤100000
这该说点什么,最大的暴力就是直接输出Failed ,然而我和我的小伙伴都以为至少30+,然而好像只有 FIVE
//三十分的数据根据美观程度sort,然后找符合的瞎搞搞就好了
100算法:我们先将魔石和法宝的美观程度(第二关键字)按从大到小排序,然后对于每件法宝,我们枚举魔石的美观程度,如果合法,把魔石的价钱插入到平衡树中,然后在平衡树中找法宝要求的法力值的后继,如果找不到,就输出Failed,找完之后把该价钱从平衡树中删除,顺便记录一下答案,输出即可。
最后注意使用long long,否则会爆掉。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<ctime> 7 #include<algorithm> 8 using namespace std; 9 long long ans; 10 int n,m,len,root,temp; 11 struct node1{int l,r,v,w,fix;}tr[100100]; 12 struct node2{int x,y; bool operator<(const node2 a)const{return y>a.y;}}g[100100],c[100100]; 13 void lturn(int &p) {int c=tr[p].r; tr[p].r=tr[c].l; tr[c].l=p; p=c;} 14 void rturn(int &p) {int c=tr[p].l; tr[p].l=tr[c].r; tr[c].r=p; p=c;} 15 inline int read() 16 { 17 int x=0,f=1; char ch=getchar(); 18 while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getchar();} 19 while(isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();} 20 return x*f; 21 } 22 void insert(int &p,int v) 23 { 24 if(!p) {p=++len; tr[p].v=v; tr[p].w=1; tr[p].fix=rand(); return;} 25 if(v==tr[p].v) tr[p].w++; 26 else if(v<tr[p].v) {insert(tr[p].l,v); if(tr[p].fix>tr[tr[p].l].fix) rturn(p);} 27 else {insert(tr[p].r,v); if(tr[p].fix>tr[tr[p].r].fix) lturn(p);} 28 } 29 void del(int &p,int v) 30 { 31 if(tr[p].v==v) 32 { 33 if(tr[p].w>1) tr[p].w--; 34 else if(tr[p].l*tr[p].r==0) p=tr[p].r+tr[p].l; 35 else if(tr[tr[p].l].fix<tr[tr[p].r].fix) {rturn(p); del(p,v);} 36 else {lturn(p); del(p,v);} 37 } 38 else if(v<tr[p].v) del(tr[p].l,v); 39 else del(tr[p].r,v); 40 } 41 void find(int p,int v) 42 { 43 if(!p) return; 44 if(tr[p].v>=v) {temp=tr[p].v; find(tr[p].l,v);} 45 else find(tr[p].r,v); 46 } 47 int main() 48 { 49 freopen("moking.in","r",stdin); 50 freopen("moking.out","w",stdout); 51 n=read(); m=read(); 52 for(int i=1;i<=n;i++) c[i].x=read(),c[i].y=read(); 53 for(int i=1;i<=m;i++) g[i].x=read(),g[i].y=read(); 54 sort(c+1,c+n+1); sort(g+1,g+m+1); 55 int j=1; 56 for(int i=1;i<=n;i++) 57 { 58 temp=-1; 59 while(g[j].y>=c[i].y&&j<=m) {insert(root,g[j].x); j++;} 60 find(root,c[i].x); 61 if(temp==-1) {printf("Failed\n"); return 0;} 62 ans+=temp; del(root,temp); 63 } 64 printf("%I64d\n",ans); 65 return 0; 66 }
最大估计 145.
立flag
1.哈希表
2.并查集
3.01背包