zoukankan      html  css  js  c++  java
  • 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
    ");  return 0;}
    62         ans+=temp;  del(root,temp);
    63     }
    64     printf("%I64d
    ",ans);
    65     return 0;
    66 }

    最大估计 145.

    立flag

    1.哈希表

    2.并查集

    3.01背包

    No matter how you feel, get up , dress up , show up ,and never give up.
  • 相关阅读:
    PHP mysqli_sqlstate() 函数
    修改用户家目录
    mysql 我的学习
    mysql 表空间
    mysql cluster 运行的必备条件
    浅谈mysql集群
    RBAC权限管理
    mysql 恢复备份
    oracle10G/11G官方下载地址集合 直接迅雷下载
    MySQL 全文搜索支持, mysql 5.6.4支持Innodb的全文检索和类memcache的nosql支持
  • 原文地址:https://www.cnblogs.com/Kaike/p/5859627.html
Copyright © 2011-2022 走看看