首先,我想说今天的题目都让我觉得好感动,至少都有一点思路,差不多可以做出来了,很开心,昨天的题目是真的恶心。
然后开始记录打卡啦!!!
You are preparing for an exam on scheduling theory. The exam will last for exactly T milliseconds and will consist of n problems. You can either solve problem i in exactly ti milliseconds or ignore it and spend no time. You don't need time to rest after solving a problem, either.
Unfortunately, your teacher considers some of the problems too easy for you. Thus, he assigned an integer ai to every problem i meaning that the problem i can bring you a point to the final score only in case you have solved no more than ai problems overall (including problem i).
Formally, suppose you solve problems p1, p2, ..., pk during the exam. Then, your final score s will be equal to the number of values of jbetween 1 and k such that k ≤ apj.
You have guessed that the real first problem of the exam is already in front of you. Therefore, you want to choose a set of problems to solve during the exam maximizing your final score in advance. Don't forget that the exam is limited in time, and you must have enough time to solve all chosen problems. If there exist different sets of problems leading to the maximum final score, any of them will do.
The first line contains two integers n and T (1 ≤ n ≤ 2·105; 1 ≤ T ≤ 109) — the number of problems in the exam and the length of the exam in milliseconds, respectively.
Each of the next n lines contains two integers ai and ti (1 ≤ ai ≤ n; 1 ≤ ti ≤ 104). The problems are numbered from 1 to n.
In the first line, output a single integer s — your maximum possible final score.
In the second line, output a single integer k (0 ≤ k ≤ n) — the number of problems you should solve.
In the third line, output k distinct integers p1, p2, ..., pk (1 ≤ pi ≤ n) — the indexes of problems you should solve, in any order.
If there are several optimal sets of problems, you may output any of them.
5 300
3 100
4 150
4 80
2 90
2 300
2
3
3 1 4
2 100
1 787
2 788
0
0
2 100
2 42
2 58
2
2
1 2
In the first example, you should solve problems 3, 1, and 4. In this case you'll spend 80 + 100 + 90 = 270 milliseconds, falling within the length of the exam, 300 milliseconds (and even leaving yourself 30 milliseconds to have a rest). Problems 3 and 1 will bring you a point each, while problem 4 won't. You'll score two points.
In the second example, the length of the exam is catastrophically not enough to solve even a single problem.
In the third example, you have just enough time to solve both problems in 42 + 58 = 100 milliseconds and hand your solutions to the teacher with a smile.
这个是一个贪心的题目,果然贪心千变万化,有点难啊,不过呢,这个比之前我写的好多了。
有点思路,但是还是不会写。
这个题目应该是对时间进行贪心,然后再满足时间的条件下,用优先队列来维护答案,
这就可以既满足时间的要求,又满足了对分数的要求。
我现阶段的对贪心的认识就是,一般比较简单的贪心都只要对一个进行贪心就可以了,
然后稍微进阶一点的就是这种,对两个进行贪心,而且还有一点点的冲突,需要好好处理。
然后更加恶心的就是昨天那种,不过昨天的可以不用贪心写。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cstring>
#include <iostream>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 100;
struct node
{
int id, goal, time;
friend bool operator<(const node&a,const node &b)
{
if (a.goal == b.goal) return a.time < b.time;
return a.goal > b.goal;
}
}exa[maxn];
priority_queue<node>que;
bool cmp(node a,node b)
{
if (a.time == b.time) return a.goal > b.goal;
return a.time < b.time;
}
int main()
{
ll ans = 0;
int n, t;
cin >> n >> t;
for(int i=1;i<=n;i++)
{
cin >> exa[i].goal >> exa[i].time;
exa[i].id = i;
}
sort(exa + 1, exa + 1 + n, cmp);
for(int i=1;i<=n;i++)
{
if (exa[i].time > t) break;
if(exa[i].time<=t)
{
t -= exa[i].time;
ans++;
que.push(exa[i]);
}
while(!que.empty()&&que.top().goal<ans)
{
t += que.top().time;
ans--;
que.pop();
}
}
printf("%lld\n", ans);
printf("%d\n", que.size());
while(!que.empty())
{
printf("%d ", que.top().id);
que.pop();
}
printf("\n");
return 0;
}
There are nn distinct points on a coordinate line, the coordinate of ii-th point equals to xixi. Choose a subset of the given set of points such that the distance between each pair of points in a subset is an integral power of two. It is necessary to consider each pair of points, not only adjacent. Note that any subset containing one element satisfies the condition above. Among all these subsets, choose a subset with maximum possible size.
In other words, you have to choose the maximum possible number of points xi1,xi2,…,ximxi1,xi2,…,xim such that for each pair xijxij, xikxik it is true that |xij−xik|=2d|xij−xik|=2d where dd is some non-negative integer number (not necessarily the same for each pair of points).
The first line contains one integer nn (1≤n≤2⋅1051≤n≤2⋅105) — the number of points.
The second line contains nn pairwise distinct integers x1,x2,…,xnx1,x2,…,xn (−109≤xi≤109−109≤xi≤109) — the coordinates of points.
In the first line print mm — the maximum possible number of points in a subset that satisfies the conditions described above.
In the second line print mm integers — the coordinates of points in the subset you have chosen.
If there are multiple answers, print any of them.
6
3 5 4 7 10 12
3
7 3 5
5
-1 2 5 8 11
1
8
In the first example the answer is [7,3,5][7,3,5]. Note, that |7−3|=4=22|7−3|=4=22, |7−5|=2=21|7−5|=2=21 and |3−5|=2=21|3−5|=2=21. You can't find a subset having more points satisfying the required property.
这个题目,很明显是一个找规律的题目,我也发现了,但是可惜,并没有完全找到,然后搜了一下题解,
你会发现这个最多就是三个,最少就是一个(这个不要找规律,看清楚题目,或者WA几发就发现了)
这个 最多就是三个的规律,你可以自己推一下,很简单
就是对 x,x+2^d,x+2^d1 这个是三个的,然后你就会发现就是这个三个进行排列x在中间,然后还有就是d1和d相差一个1,自己手动推一下吧。
如果是四个,你会发现无法满足。
知道这个就很好做了。 用map存数进去,再枚举2的幂,到30就好了,然后再枚举每一个数是不是有可能满足。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cstring>
#include <map>
#include <iostream>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 100;
map<ll, int>mp;
ll a[maxn];
ll p[maxn];
void pow()
{
for(int i=0;i<=30;i++)
{
p[i] = 1;
for(int j=1;j<=i;j++)
{
p[i] *= 2;
}
//printf("p[%d]=%lld\n", i, p[i]);
}
}
int main()
{
int n;
cin >> n;
mp.clear();
for(int i=1;i<=n;i++)
{
ll x;
cin >> x;
a[i] = x;
mp[x] = 1;
}
pow();
sort(a + 1, a + 1 + n);
int flag=0, mark=0,num=0,m=0,fl=0;
for(int i=0;i<=30;i++)
{
flag = 0;
for(int j=1;j<=n;j++)
{
//printf("%d %d %lld %lld %d\n",i, j, a[j], a[j] + p[i],mp[a[j]+p[i]]);
flag = 0;
//printf("qqq\n");
if(mp[a[j]+p[i]]==1&&a[j]!=a[j]+p[i])
{
m = i;
num = j;
}
if (mp[a[j] + p[i]] == 1 && mp[a[j] + p[i + 1]] == 1)
{
if (a[j] == a[j] + p[i] || a[j] == a[j] + p[i + 1] || a[j] + p[i] == a[j] + p[i + 1]) continue;
mark = i;
flag = j;
break;
}
}
if (flag) break;
}
if(flag)
{
printf("3\n");
printf("%lld %lld %lld\n", a[flag], a[flag] + p[mark], a[flag] + p[mark + 1]);
}
else if(num)
{
printf("2\n");
printf("%lld %lld\n", a[num], a[num] + p[m]);
}
else
{
printf("1\n");
printf("%lld\n", a[1]);
}
// else printf("0\n");
return 0;
}
Professor GukiZ doesn't accept string as they are. He likes to swap some letters in string to obtain a new one.
GukiZ has strings a, b, and c. He wants to obtain string k by swapping some letters in a, so that k should contain as many non-overlapping substrings equal either to b or c as possible. Substring of string x is a string formed by consecutive segment of characters from x. Two substrings of string x overlap if there is position i in string x occupied by both of them.
GukiZ was disappointed because none of his students managed to solve the problem. Can you help them and find one of possible strings k?
The first line contains string a, the second line contains string b, and the third line contains string c (1 ≤ |a|, |b|, |c| ≤ 105, where |s| denotes the length of string s).
All three strings consist only of lowercase English letters.
It is possible that b and c coincide.
Find one of possible strings k, as described in the problem statement. If there are multiple possible answers, print any of them.
aaa
a
b
aaa
pozdravstaklenidodiri
niste
dobri
nisteaadddiiklooprrvz
abbbaaccca
ab
aca
ababacabcc
In the third sample, this optimal solutions has three non-overlaping substrings equal to either b or c on positions 1 – 2 (ab), 3 – 4 (ab), 5 – 7 (aca). In this sample, there exist many other optimal solutions, one of them would be acaababbcc.
这个题目,我想法就想错了,我开始以为是贪心,后来发现并不是,这个不是的反例我也是看别人的博客的。
其实呢,你仔细看看这个数据范围,应该就可以发现了,应该不是贪心,一般贪心的数据范围有点大,无法枚举。
而且这个题目用贪心你自己不觉得有点小慌吗?反正我当时用就挺慌的,感觉不太对。
这个可以直接暴力枚举,因为这个只有1e5,所以你可以枚举B或者C字符串的数量,这个你不要觉得困难,
困难的话,你用贪心先写一次,然后再来看,你会发现很简单的。
对于枚举B,C有两种,一种就是每个都枚举一次,看哪个更好,
还有就是只枚举数量更多的那个,这个是因为如果你枚举数量小的话,如果出现numb=0,numc!=0那你就凉凉了,
接下来就是看代码的时候了/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cstring>
#include <map>
#include <string>
#include <iostream>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 100;
string s, a, b;
int vis[30], bis[maxn];
int via[30], vib[30];
int main()
{
int numa = inf, numb = inf;
int otha = inf, othb = inf;
cin >> s >> a >> b;
int len = s.size();
int lena = a.size();
int lenb = b.size();
memset(vis, 0, sizeof(vis));
memset(via, 0, sizeof(via));
memset(vib, 0, sizeof(vib));
for (int i = 0; i < len; i++) vis[s[i] - 'a']++;
for (int i = 0; i < lena; i++) via[a[i] - 'a']++;
for (int i = 0; i < lenb; i++) vib[b[i] - 'a']++;
for (int i = 0; i <= 26; i++)
{
if (via[i] == 0) continue;
numa = min(numa, vis[i] / via[i]);
}
for (int i = 0; i <= 26; i++)
{
if (vib[i] == 0) continue;
numb = min(numb, vis[i] / vib[i]);
}
// printf("%d %d\n", numa, numb);
int ans = 0, mark = 0;
if(numa>numb)
{
for(int i=1;i<=numa;i++)
{
for (int j = 0; j < 26; j++) bis[j] = vis[j];
for(int j=0;j<26;j++)
{
bis[j] -= via[j] * i;
}
//求在枚举a的状态下,b的最多的数。
for(int j=0;j<26;j++)
{
if (vib[j] == 0) continue;
otha = min(otha, bis[j] / vib[j]);
}
if(i+otha>ans)
{
ans = i + otha;
mark = i;
}
}
}
else
{
for(int i=1;i<=numb;i++)
{
// printf("i=%d\n", i);
for (int j = 0; j < 26; j++) bis[j] = vis[j];
for(int j=0;j<26;j++)
{
bis[j] -= vib[j] * i;
//printf("bis[%d]=%d\n", j, bis[j]);
}
// 在枚举b的情况下,求a得到的最多的子串数
for(int j=0;j<26;j++)
{
if (via[j] == 0) continue;
othb = min(othb, bis[j] / via[j]);
//printf("othb=%d \n", othb);
}
if(othb+i>ans)
{
ans = othb + i;
mark = othb;
//printf("ans=%d mark=%d\n", ans, mark);
}
}
}
//printf("%d %d\n", mark, ans);
for (int i = 0; i < mark; i++) cout << a;
for (int i = 0; i < ans - mark; i++) cout << b;
for(int i=0;i<26;i++)
{
vis[i] = vis[i] - via[i] * mark - vib[i] * (ans - mark);
if (vis[i] <= 0) continue;
for (int j = 0; j < vis[i]; j++) printf("%c", 'a' + i);
}
printf("\n");
return 0;
}
The start of the new academic year brought about the problem of accommodation students into dormitories. One of such dormitories has a a × b square meter wonder room. The caretaker wants to accommodate exactly n students there. But the law says that there must be at least 6 square meters per student in a room (that is, the room for n students must have the area of at least 6n square meters). The caretaker can enlarge any (possibly both) side of the room by an arbitrary positive integer of meters. Help him change the room so as all nstudents could live in it and the total area of the room was as small as possible.
The first line contains three space-separated integers n, a and b (1 ≤ n, a, b ≤ 109) — the number of students and the sizes of the room.
Print three integers s, a1 and b1 (a ≤ a1; b ≤ b1) — the final area of the room and its sizes. If there are multiple optimal solutions, print any of them.
3 3 5
18
3 6
2 4 4
16
4 4
这个题目1800的分数,我觉得也太不应该了,这个题目虽然不说是傻逼题,不过真的不难。
开始以为是二分,后来发现不需要用二分写。。。。
不过。。。我T了,然后还不知道怎么优化。。。。?
后来看了题解,发现离A就差一两步。。。?
这个主要就是给你一个数字n,还有a,b让你求a1,b1
要求就是a1*b1>=6*n
这个可以直接暴力就可以了,暴力到根号下6*n,就好了
不过开始我因为我直接开根号然后+1不对,其实还需要再加1,这个我一个一个查出来的。。。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <cstring>
#include <map>
#include <string>
#include <iostream>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 100;
int main()
{
ll n, a, b, x = 0, y = 0;
cin >> n >> a >> b;
if (a > b) swap(a, b);
if (a*b > 6 * n)
{
printf("%lld\n", a*b);
printf("%lld %lld\n", a, b);
return 0;
}
ll len = sqrt(6 * n) + 1;
for (int i = a; i <= len; i++)
{
//printf("i=%d\n", i);
if (6*n%i == 0 && 6*n / i >= b)
{
x = i;
y = 6*n / i;
break;
}
if (i*b > 6*n)
{
x = i;
y = b;
break;
}
}
printf("%lld\n", x*y);
printf("%lld %lld\n", x, y);
return 0;
}