一天之后,计蒜客第二场,感觉一般般,第一题卡了一下处理的比较慢,导致后面时间略微不足,第二题倒是没什么坑点
A. 淘宝的推荐系统
思路:这题dp的味道还是挺明显的,dp选择当前元素所能达到的最大长度,至于转移,第一次想的是转移之前所有状态中可能的状态,然而O(n^2)的复杂度,加上多组数据,毫无疑问tle
之后想到用d,转移可能的状态,而不是转移先前的状态,用map存储状态,然而,map只是重载了下标运算符,内部红黑树实现O(log(n))的复杂度,结果还是被卡掉了
于是想到各种优化,优化cin,优化运算,优化函数等各种,然而依然杯水车薪
于是想到set预处理已经出现过的状态,实现离散化,二分查找离散化后的状态来优化原来的暴力枚举,结果依然tle
最后猛然发现状态的数据范围仅有5次方,于是果断回到第二种做法,还原map为数组,顺利ac,好吧,醉了
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <map>
#include <cmath>
#include <string>
#include <queue>
#include <stack>
#include <set>
using namespace std;
const int N = 200;
const int maxn = 2e5+10;
/*
int p[maxn];
set<int> p;
int dp[maxn];
map <int,int> dp;
int myabs(int k)
{
if(k<0)
{
k *= (-1);
}
return k;
}
int main()
{
int t;
//ios::sync_with_stdio(false);
scanf("%d",&t);
while(t--)
{
p.clear();
int n,d;
//cin >> n >> d ;
scanf("%d%d",&n,&d);
int maxl = 1;
for(int i=0;i<n;i++)
{
//cin >> p[i];
int pp;
scanf("%d",&pp);
dp[pp] = 1;
set<int> :: iterator it = p.lower_bound(pp-d);
for(;it!=p.end()&&(*it)<=pp+d;it++)
{
//if(myabs(p[i] - p[j])<=d)
//if(((p[i] - p[j]) <= d )&& ((p[i] - p[j]) >= ((-1)*d)))
//{
//cout << (*it) << "&&" << dp[(*it)] << endl;
if(dp[(*it)]+1>dp[i])
{
dp[pp] = dp[(*it)]+1;
}
//}
}
p.insert(pp);
if(dp[pp] > maxl)
{
maxl = dp[pp];
}
}
//cout << maxl << endl;
printf("%d\n",maxl);
}
}*/
//map<int,int> dp;
int dp[maxn];
int main()
{
int t;
//ios::sync_with_stdio(false);
scanf("%d",&t);
//cout << dp[0];
while(t--)
{
//dp.clear();
memset(dp,0,sizeof(dp));
int n,d;
//cin >> n >> d ;
scanf("%d%d",&n,&d);
int maxl = 1;
for(int i=0;i<n;i++)
{
int p;
//cin >> p[i];
scanf("%d",&p);
//dp[i] = 1;
int now = 1;
for(int j=p-d;j<=p+d;j++)
{
//cout << j << "#" <<dp[j]<< endl;
//if(myabs(p[i] - p[j])<=d)
int temp = dp[j+N] + 1;
if(temp > now)
{
now = temp;
//cout << j << "#" <<dp[j]<< endl;
}
}
dp[p+N] = now;
//cout << dp[p] << "*" << endl;
if(now > maxl)
{
maxl = now;
}
}
//cout << maxl << endl;
printf("%d\n",maxl);
}
}
//O(n^2)
//O(2*n*d*log(n))
//优化
//O(n*(log(n)+d)*log(n))
//O(2*n*d)
B. 阿里巴巴的手机代理商(简单)
思路:这题就是个字符串大模拟,map存取键值,后缀都采用substr截断判断,毕竟处于简单位置,比较友好
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <map>
#include <cmath>
#include <string>
#include <queue>
#include <stack>
using namespace std;
const int maxn = 1e5+10;
map<string,int> col;
int main()
{
int t;
ios::sync_with_stdio(false);
cin >> t;
while(t--)
{
col.clear();
int n;
cin >> n;
while(n--)
{
string temp;
cin >> temp;
if(temp=="insert")
{
string cha;
int num;
cin >> cha >> num;
col[cha] += num;
}
else if(temp=="delete")
{
string cha;
cin >> cha;
if(col[cha] == 0)
{
cout << "Empty\n";
}
else
{
col[cha] = 0;
}
}
else if(temp=="query")
{
string cha;
cin >> cha;
int len = cha.size();
map<string,int> :: iterator it;
int re = 0;
for(it = col.begin();it!=col.end();it++)
{
string ch = it->first;
int nnum = it->second;
int nlen = ch.size();
if(nlen<len)
{
continue;
}
ch = ch.substr(nlen-len,len);
if(ch == cha)
{
re += nnum;
}
}
cout << re << "\n";
}
}
}
return 0;
}