base 2:
题意:
给你一个序列a0,a1,a2.....a63。让你求他所a0*2^0+a1*2^1+......+a63*2^63次方。
思路:
这题很好理解,就是一个转进制的基础问题,但是要注意一点,long long有一位是符号位,所以要用unsigned long long来储存。使用pow()函数的朋友,记得用unsigned long long接收一下,默认返回是double类型,太小了。
代码:是
#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
#include<map>
#include<stack>
#include<set>
#include<queue>
using namespace std;
string s;
#define maxn 500020
#define ll long long
#define int unsigned long long
int dp[maxn][2];
int a[maxn];
multiset<int,greater<int>>c,b;
int cmp(int a, int b)
{
return a > b;
}
void solve()
{
int k=1;
int ans=0,n;
for (int i = 0; i <= 63; i++)
{
cin >> n;
ans += n * k;
k <<= 1;
}
cout << ans;
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
solve();
return 0;
}
Centers:
题意:
给你一个序列,长度为3*n。让你按照他们按中间数出现的先后排序,即按照第二个数出现的顺序排序。
思路:
第二次出现的时候,直接打印。
代码:
#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
#include<map>
#include<stack>
#include<set>
#include<queue>
using namespace std;
string s;
#define maxn 500020
#define ll long long
#define int long long
int dp[maxn][2];
int a[maxn];
multiset<int,greater<int>>c,b;
map<int, int>m;
int cmp(int a, int b)
{
return a > b;
}
void solve()
{
int n;
cin >> n;
int x;
for (int i = 1; i <= 3*n; i++)
{
cin >> x;
m[x]++;
if (m[x] == 2)
cout << x<<" ";
}
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
solve();
return 0;
}
Poisonous Full-Course
题意:
一共有两种食物,有毒的和解毒的,都有一定的美味值(饱食度),按给你的顺序,你可以选择吃或跳过,要求获得的美味值(饱食度?)最大(不能寄)。如果你现在没中毒,你吃了有毒的事物会中毒,吃解毒事物没事;如果你现在中毒了,吃有毒的就寄了,吃解毒的可以恢复到没中毒的状态。初始健康没中毒。
思路:
我一开始没想到dp,各种if+调试半小时没写出来。大佬用dp很快写出来了。首先每一道菜上场的时候,都有类问题,吃或者不吃,当时是否中毒。dp[maxn][2],二维中的1代表中毒,0代表解毒。代码有注释。
代码:
#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
#include<map>
#include<stack>
#include<set>
#include<queue>
using namespace std;
string s;
#define maxn 500020
#define ll long long
#define int long long
int dp[maxn][2];
int a[maxn];
multiset<int,greater<int>>c,b;
map<int, int>m;
//b中保存的是前k个最大的,c中是全部的(按顺序)
//至于a用来检索
int cmp(int a, int b)
{
return a > b;
}
void solve()
{
int n;
cin >> n;
int x,y;
for (int i = 1; i <= n; i++)
{
cin >> x >> y;
if (x == 1)//当前事物有毒
{
//没中毒
dp[i][0] = dp[i - 1][0];
//中毒了可能是下列情况转化来的
dp[i][1] = max(dp[i - 1][1],dp[i - 1][0] + y);
}
if (x == 0)//当前食物没毒
{
//中毒了,没吃
dp[i][1] = dp[i - 1][1];
//没中毒,可能没吃这个,可能是中毒了吃这个,没中毒吃这个。
dp[i][0] = max(dp[i - 1][0], max(dp[i - 1][1] + y, dp[i - 1][0] + y));
}
}
cout << max(dp[n][0], dp[n][1]) << endl;;
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
solve();
return 0;
}
Best Perform:
题意:
一共n个数,q次查询,每一次查询,我们需要找到最大的前k个数,然后输出他们的和。k次查询也有讲究,每次查询输入x,y。x是下标,把下标为x的数改成y,然后重新计算和。
思路:
我想的是开3个数组做,每次都sort排序一下,后来看大佬用的multiset,确实好用,我就用这个做了。中保存的是前k个最大的,c中是剩下n-k的个按顺序。具体看代码
代码:
#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
#include<map>
#include<stack>
#include<set>
#include<queue>
using namespace std;
string s;
#define maxn 500020
#define ll long long
#define int long long
int dp[maxn][2];
int a[maxn];
multiset<int, greater<int>> b,c;
//b中保存的是前k个最大的,c中是剩下n-k的个按顺序
// 有人可能会问c有啥用,举个例子。五个数 5 4 3 2 1,k=4,sum=14
// 现在我把第一个数5改成0,理论上和为10(4+3+2+1),没这个列表无法实现这个功能
//至于a用来检索
int cmp(int a, int b)
{
return a > b;
}
void solve()
{
int n, k, q;
cin >> n >> k >> q;
int ans = 0;
int x, y;
for (int i = 1; i <= q; i++)
{
cin >> x >> y;
//这个数在前k个中,因为不知道改大改小,所以先删掉。
if (b.size() && b.find(a[x]) != b.end())
{
b.erase(b.find(a[x]));
ans -= a[x];
}
//在另外
else if(c.size()&& c.find(a[x]) != c.end())
c.erase(c.find(a[x]));
//删完直接插进c,然后和b中最小的比较。
c.insert(y);
a[x] = y;
//不满的时候
while (b.size() < k && c.size())
{
b.insert(*c.begin());
ans += *c.begin();
c.erase(c.begin());
}
//满了但是新来的大
while (c.size() && *b.rbegin() < *c.begin())
{
ans -= *b.rbegin();
ans += *c.begin();
b.insert(*c.begin());
c.insert(*b.rbegin());
b.erase(b.find(*b.rbegin()));
c.erase(c.find(*c.begin()));
}
cout << ans << endl;
}
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
solve();
return 0;
}