**2019山东省赛重现 **
萌新又来写记录了
***A - Calandar ***
tips:每个月都只有30天,直接转化成天为单位算就可以~ 注意可以是之前的时间,也可以是之后的,开long long存~
#include<bits/stdc++.h>
#define ll long long
using namespace std;
string book[] = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday"};
ll t,year,mon,day,a,b,c,now;
string s;
int main(){
scanf("%d",&t);
while(t--){
scanf("%lld%lld%lld",&year,&mon,&day);
cin >> s;
scanf("%lld%lld%lld",&a,&b,&c);
ll buff = ((a - year) * 360 + (b - mon) * 30 + (c - day)) % 5;
if(buff < 0) buff += 5;
for(int i = 0; i < 5; i++) //这里也可以用map存,然后直接查询
if(book[i] == s)
now = i;
cout << book[(now + buff) % 5] << endl;
}
return 0;
}
**C - Wandering Robot ***
tips:不是算完一次然后k就可以!应该是找到第k-1次的终点,然后从这个终点再跑最后一次~(取得的最大值只可能在第一次或者最后一次)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll ans,n,t,k,len,x,y,endx,endy,maxx,maxy;
string command;
void solve(int i){
if(command[i] == 'U') y += 1;
if(command[i] == 'D') y -= 1;
if(command[i] == 'R') x += 1;
if(command[i] == 'L') x -= 1;
}
int main(){
scanf("%d",&t);
while(t--){
ans = x = y = 0;
scanf("%d%d",&n,&k);
cin >> command;
len = command.length();
for(int i = 0; i < len; ++i){
solve(i);
ans = max(ans, abs(x) + abs(y));
}
endx = x * (k - 1), endy = y * (k - 1);
/*printf("endx = %d endy = %d \n",endx,endy);
ans = max(ans, abs(endx) + abs(endy));*/
x = endx, y = endy;
for(int i = 0; i < len; ++i){
solve(i);
ans = max(ans, abs(x) + abs(y));
}
printf("%lld\n",ans);
}
return 0;
}
***D - Game on a Graph ***
tips:图论(离散数学)的应用。一个无向简单连同图,最少要有n-1条边。所以第m-(n-1)条边是谁选,该队伍就输~(注意要mod k,因为是循环选的,即队伍的最后一个人选完,接着轮到第一个人选)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int t,k,book[100005],n,m,u,v;
int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&k);
for(int i = 0; i < k; ++i)
scanf("%1d",&book[i]);
scanf("%d%d",&n,&m);
for(int i = 1; i <= m; ++i)
scanf("%d%d",&u,&v);
int temp = (m - (n - 1)) % k;
book[temp] == 1 ? printf("2\n") : printf("1\n");
}
return 0;
}
***F - Stones in the Bucket ***
tips:贪心。两个策略分别为:A.每次拿出一块石头 B.每次拿出一块石头放入另一个
可以发现,最后的状态是ave = sum / n;
对于等于ave的桶,不作处理;
对于小于ave的桶,只能由大于ave的桶采取B策略,所以可以暂时忽略,等到大于ave的桶时在计算;
对于大于ave的桶,ans += book[i] - ave;(要么是给小于ave的桶(B策略);要么是A策略直接扔掉)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll t,book[100005],sum,ave,ans,n;
int main(){
scanf("%d",&t);
while(t--){
scanf("%lld",&n);
sum = ans = 0;
for(int i = 1; i <= n; ++i){
scanf("%lld",&book[i]);
sum += book[i];
}
ave = sum / n;
if(!ave) printf("%lld\n",sum);
else{
for(int i = 1; i <= n; ++i){
if(book[i] < ave || book[i] == ave) continue;
else if(book[i] > ave)
ans += book[i] - ave;
}
printf("%lld\n",ans);
}
}
return 0;
}
***H - Tokens on the Segments ***
tips:贪心+优先队列!
这个题还是很好玩的,值得整理一下~
线段短的应该优先考虑(因为长的可选择的点(机会)多,短的(例如只有一个点)机会少,应该先选。按照左端点排序会有两种情况:A.某一条线段的左端点是唯一的,只需要选择这个点,就可以选择这个线段,而不影响其他线段;B.不唯一,按照线段长短来选择)
这种线段+区间的问题,一般都会 按左端点小到大排序,左端点相同则右端点小到大排序~(不绝对,但是这是一种可以考虑的思路,反过来也行)。这样排序在左端点相同的情况下,按照线段短->长的顺序考虑。结构体中重载小于号,然后用优先队列维护线段。last记录上一次选取的点的x坐标。
若l > last,则cnt++, last = l;
否则如果last + 1 <= r(<号不可以去掉~)把l更改成last + 1再放入优先队列中等待下一次计算!(而不是直接选这条线段的第last + 1个点,如下图情况)
#include<bits/stdc++.h>
#include<queue>
#define ll long long
using namespace std;
struct node{
int l,r;
bool operator < (const node& rhs) const{
if(rhs.l != l) return l > rhs.l;
else return r > rhs.r;
}
node(int lll, int rr){l = lll, r = rr;}
node(){};
}book[100005];
int t,n,last,cnt;
int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);
priority_queue<node> q;
for(int i = 1; i <= n; ++i){
scanf("%d%d",&book[i].l,&book[i].r);
q.push(book[i]);
}
last = cnt = 0;
while(!q.empty()){
node n1 = q.top(); q.pop();
if(last < n1.l) last = n1.l, cnt++;
else{
if(last + 1 <= n1.r)
q.push(node(last + 1, n1.r));
}
}
printf("%d\n",cnt);
}
return 0;
}
**M - Sekiro ***
tips:直接算肯定会超时。写一写就会发现,k每增加1,n就会2,是2的指数关系。因为n不超过10的9次方,大约2的31次方就已经超过这个值了,直接给答案1就可以~ 注意n/2要转化成double,否则5/2==2~
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int t,n,k;
int main(){
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&k);
if(!n) printf("0\n");
else if(k >= 50) printf("1\n"); //可以再小一点,随便啦
else{
for(int i = 1; i <= k; ++i){
n = ceil((double)n / 2);
if(n == 1) break;
}
printf("%d\n",n);
}
}
return 0;
}