首页 > 代码库 > Test on 09/10/2016
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背包
Test on 09/10/2016