1.Question:
-
输入
-
第一行有一个整数n(0<n<=10000);
随后有n行;
每行可能出现如下的任意一种形式:
第一种:
一个字符串"ADD",接着是一个整数m,随后有m个i;
第二种:
一个字符串"QUERY”,接着是一个整数M,随后有M个ki;
输出
- 输出每次询问的结果"YES"或"NO". 样例输入
-
2 ADD 5 34 343 54 6 2 QUERY 4 34 54 33 66
样例输出
-
YES YES NO NO
2.Solution:
本题的数据量非常的大,而且还涉及到了不断的添加和查询操作
所以,简单的排序加二分的思路已经是走不通了,在这里我们用哈希
哈希的思路世纪路节点的存在,但是本题有一点巧妙而就是本题的内存非常的节约
65536kb的内存,我们如果只是简简单单的开100000000的int或者short的话我们看一下内存数据的占用情况
首先拿short来看吧,一个short两个字节,那么总共要200000000b,约为200000kb,很显然超过内存
所以在这里我们的解题思路很明显就是缩小我们的哈希表长
我才用的是1000000的表长,对于超出表唱的部分我们采用除留取余法,
但是这样我哦们是没有办法避免冲突的,采用拉链法我们可以尽可能的节约我们的内存
对于我们插入的内存优化,我们可以通过找到相同的然后不插入,但是这样的优化空间可以提升但是我们每次的查询都需要耗费一定量的遍历操作的时间,如果我们的冲突的频度非常大的话,还是会提高我们的时间的复杂度
在本题的测试数据中,我对两种思路都进行了测试,发现内存并没有减少,时间还提升了,说明我们的测试数据中的所有的只都是不相同的,导致我们的第二种思路的时间效率低于第一种的时间效率
3.Code:
#include"iostream"
#include"cstdio"
#include"cstring"
#include"cstdlib"
using namespace std;
typedef struct node
{
int x;
struct node* next;
}point;
point hash[1000000];
int n;
int m;
char atom[10];
void init()
{
for(int i=0;i<1000000;i++) hash[i].next=NULL;
}
int main()
{
init();
scanf("%d",&n);
while(n--)
{
scanf("%s%d",atom,&m);
if(strcmp(atom,"ADD")==0)
{
for(int i=0;i<m;i++)
{
int x;
scanf("%d",&x);
point* w=new point;
w->x=x;
bool flag=false;
point* p=hash[x%1000000].next;
while(p!=NULL)
{
if(p->x==x)
{
flag=true;
break;
}
p=p->next;
}
if(!flag)
{
w->next=hash[x%1000000].next;
hash[x%1000000].next=w;
}
}
}
else
{
for(int i=0;i<m;i++)
{
int x;
scanf("%d",&x);
bool flag=false;
point* w=hash[x%1000000].next;
while(w!=NULL)
{
if(w->x==x)
{
flag=true;
break;
}
w=w->next;
}
if(flag) printf("YES\n");
else printf("NO\n");
}
}
}
return 0;
}