PREV237:答疑
答疑
题意:
n个学生找老师答疑。第i个学生的进入办公室和答疑的时长为
s
i
+
a
i
s_i+a_i
si+ai,答疑完成后在课程群发送消息,然后花
e
i
e_i
ei的时间离开办公室。之后下一个学生进入。求所有学生的发送消息的时刻之和的最小值。
思路:
贪心排序。对于学生x和y,假设先x后y,则发送时刻之和为
(
s
x
+
a
x
)
+
(
s
x
+
a
x
+
e
x
+
s
y
+
a
y
)
(s_x+a_x)+(s_x+a_x+e_x+s_y+a_y)
(sx+ax)+(sx+ax+ex+sy+ay)
同理,先y后x的发送时刻之和为:
(
s
y
+
a
y
)
+
(
s
y
+
a
y
+
e
y
+
s
x
+
a
x
)
(s_y+a_y)+(s_y+a_y+e_y+s_x+a_x)
(sy+ay)+(sy+ay+ey+sx+ax)
则当先x后y更优的适合满足
(
s
x
+
a
x
+
e
x
)
<
(
s
y
+
a
y
+
e
y
)
(s_x+a_x+e_x)<(s_y+a_y+e_y)
(sx+ax+ex)<(sy+ay+ey)。则以此进行排序。
//倒在贪心排序的坑里无数次了,这回终于反应过来了55
#include<bits/stdc++.h>
#define all(x) x.begin(),x.end()
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define pll pair<ll,ll>
#define rep(i,l,r) for(ll i = l; i <= r; i++)
#define irep(i,r,l) for(ll i = r; i >= l; i--)
//#define LOCAL
using namespace std;
typedef long long ll;
const double eps=1e-8;
const double PI=acos(-1.0);
const ll mx = 1e3 + 10;
const ll inf = 100000 + 10;
struct node{
ll s, a, e;
bool operator < (const node ob)const{
return s+a+e < ob.s+ob.a+ob.e;
}
}nos[mx];
ll n;
void solve(){
scanf("%lld", &n);
rep(i,1,n){
scanf("%lld %lld %lld", &nos[i].s, &nos[i].a, &nos[i].e);
}
sort(nos+1,nos+1+n);
ll ans = 0, ct = 0;
rep(i,1,n){
ans += (ct + nos[i].s+nos[i].a);
ct += (nos[i].s+nos[i].a+nos[i].e);
}
printf("%lld\n", ans);
}
int main(){
// cin.tie(0);
// ios::sync_with_stdio(0);
#ifdef LOCAL
freopen("1.txt", "r", stdin);
#endif
solve();
#ifdef LOCAL
fclose(stdin);
#endif
return 0;
}
PREV234:出租车(太难了放弃)
PREV231:皮亚诺曲线距离(50%)
皮亚诺曲线距离
题意:
如题
思路:
dfs求当前点到(0,0)的距离【代码中为(1,1)】。每次dfs把区间划分为9个正方形。然后发现,第二行的正方形其实相对于左下角的正方形x对称,第二列的相对于左下角的正方形y对称。坐标转换,dfs当前正方形内点到起点的距离,+当前正方形之前的正方形的点数(num数组存了之前的同大小的正方形数量)。最后把每层dfs的距离加起来(点数)得到当前点到(0,0)的距离。
根据题目,求出两个点到起点的距离之差。只能过50%的点,估计是k很大的时候没办法处理了。
#include<bits/stdc++.h>
#define all(x) x.begin(),x.end()
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define pll pair<ll,ll>
#define rep(i,l,r) for(ll i = l; i <= r; i++)
#define irep(i,r,l) for(ll i = r; i >= l; i--)
//#define LOCAL
using namespace std;
typedef long long ll;
const double eps=1e-8;
const double PI=acos(-1.0);
const ll mx = 1e6 + 10;
ll b3[200];
ll k, xa, ya, xb, yb;
ll num[4][4]={
0,0,0,0,
0,0,1,2,
0,5,4,3,
0,6,7,8
};
ll dist(ll level, ll x, ll y){
if(level == 0) return 1;
ll edge = b3[level], edge2 = b3[level-1];
ll xx = (x+edge2-1)/edge2;
ll yy = (y+edge2-1)/edge2;
// printf("level:%lld, xx:%lld, yy:%lld, x:%lld, y:%lld\n",
// level, xx, yy, x, y);
x -= (xx-1) * edge2, y -= (yy-1) * edge2;
if(yy == 2) x = edge2 - x + 1;
if(xx == 2) y = edge2 - y + 1;
ll ans = dist(level-1, x, y) + num[xx][yy] * edge2 * edge2;
return ans;
}
void solve(){
b3[0] = 1;
rep(i,1,100) b3[i] = b3[i-1] * 3;
scanf("%lld", &k);
scanf("%lld %lld %lld %lld", &xa, &ya, &xb, &yb);
xa++,ya++,xb++,yb++;
ll d1 = dist(k, xa, ya);
ll d2 = dist(k, xb, yb);
printf("%lld\n", abs(d1-d2));
}
int main(){
// cin.tie(0);
// ios::sync_with_stdio(0);
#ifdef LOCAL
freopen("1.txt", "r", stdin);
#endif
solve();
#ifdef LOCAL
fclose(stdin);
#endif
return 0;
}
PREV67:字串排序(70%)
字串排序
题意:
给定数字N,求最短的字符串使逆序对数量为N。如果存在多种方案,选择逆序对最小的方案。
思路:
DP。不知道哪里错了。也不想看了。摆……
#include<bits/stdc++.h>
#define all(x) x.begin(),x.end()
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define pll pair<ll,ll>
#define rep(i,l,r) for(ll i = l; i <= r; i++)
#define irep(i,r,l) for(ll i = r; i >= l; i--)
//#define LOCAL
using namespace std;
typedef long long ll;
const double eps=1e-8;
const double PI=acos(-1.0);
const ll mx = 2e2 + 10;
const ll N = 26;
//maxlen = 156
ll dp[mx][N+10][mx], input;
ll f[mx][N+10];//f[i][k]表示长度i,种类数k的最大逆序对数
ll query(ll len){//升序
rep(i,1,len){//第i个位置
rep(k,1,min(i,N)){//选择颜色k
dp[i][k][1] = 0;
if(k == 1)continue;
//第i-1个位置 颜色k-1 至少一个 最多(i-1)-(k-2)个
rep(j,1,i-k+1)
dp[i][k][1] = max(dp[i][k][1], dp[i-1][k-1][j]);
dp[i][k][1] += i-1;
//第i个位置 颜色k 最多 i-k+1个
rep(j,2,i-k+1)
dp[i][k][j] = dp[i-1][k][j-1]+i-j;
}
}
ll maxv = 0;
rep(j,1,len) maxv = max(maxv, dp[len][min(len,N)][j]);
return maxv;
}
ll getNiXuDui(ll len){
ll kind = 0;
rep(k,1,N){
ll maxv = 0;
rep(j,1,len) maxv = max(maxv, dp[len][k][j]);
if(maxv>=input){
kind = k;
break;
}
}
rep(i,1,len){
rep(k,1,kind){
f[i][k] = 0;
rep(j,1,len) f[i][k] = max(f[i][k],dp[i][k][j]);
}
}
return kind;
}
void solve(){
scanf("%lld", &input);
if(input == 0){//实际上没有这种输入
printf("a");
return;
}
ll zuo = 1, you = 156;
while(zuo <= you){
ll mid = (zuo + you)>>1;
ll q = query(mid);
if(q >= input) you = mid - 1;
else zuo = mid + 1;
}
ll number = zuo;
printf("mini Len: %lld\n", number);
//找到最佳颜色种类数
query(number);
ll kind = getNiXuDui(number);
printf("mini Color Num: %lld\n", kind);
//开始搭配
ll total = number;
vector<char>ans;
irep(k,kind,2){//颜色搭配 从大到小
rep(num,1,number){//k色数量为num
ll nv = num * (number - num) + f[number-num][k-1];
if(nv >= input){
input -= num * (number - num);
number -= num;
rep(i,1,num) ans.pb((char)('a'+k-1));
break;
}
}
}
ll gs = ans.size();
rep(i,0,gs-1) printf("%c",ans[i]);
rep(i,1,total - gs) printf("a");
puts("");
}
int main(){
// cin.tie(0);
// ios::sync_with_stdio(0);
#ifdef LOCAL
freopen("1.txt", "r", stdin);
#endif
solve();
#ifdef LOCAL
fclose(stdin);
#endif
return 0;
}
PREV60:回文日期
回文日期
题意:
略。
思路:
暴力。
#include <bits/stdc++.h>
#define rep(i,l,r) for(ll i = l; i <= r; i++)
//#define LOCAL
using namespace std;
typedef long long ll;
const ll mx = 1e5 + 10;
ll year, month, day;
ll d[13] = {0,
31,28,31,30,31,
30,31,31,30,31,
30,31};
ll ans1[10], ans2[10], s[10];
bool runnian(ll year){
if(year%400 == 0) return true;
if(year%100 == 0) return false;
return year%4 == 0;
}
void nextday(){
bool r = runnian(year);
if(r==false || month!=2){
if(day!=d[month]){
day++;
}
else{
day=1;
if(month!=12) month++;
else month=1,year++;
}
}
else{
if(day!=29) day++;
else day++,month++;
}
}
ll ishuiwen(){
ll ny = year;
rep(i,0,3){
s[4-i]= ny %10;
ny /= 10;
}
s[5]=month/10;
s[6]=month%10;
s[7]=day/10;
s[8]=day%10;
for(ll l=1,r=8;l<=r;l++,r--){
if(s[l]!=s[r])return -1;
}
ll a = s[1], b = s[2];
if(s[3]!=a || s[4]!=b) return 0;
return 1;
}
//ABABBABA
void solve(){
scanf("%04lld%02lld%02lld", &year,&month,&day);
bool huiwen=false;
while(1){
nextday();
ll ans = ishuiwen();
if(ans>=0 && !huiwen){
huiwen = true;
memcpy(ans1, s, sizeof s);
}
if(ans == 1){
if(!huiwen) memcpy(ans1, s, sizeof s);
memcpy(ans2, s, sizeof s);
break;
}
}
rep(i,1,8)printf("%lld",ans1[i]);
puts("");
rep(i,1,8)printf("%lld",ans2[i]);
puts("");
}
int main(){
#ifdef LOCAL
freopen("1.txt","r",stdin);
#endif
solve();
#ifdef LOCAL
fclose(stdout);
#endif
return 0;
}
PREV56:子串分值
子串分值
题意:
略。
思路:
求每个字母的贡献
#include <bits/stdc++.h>
#define rep(i,l,r) for(ll i = l; i <= r; i++)
#define irep(i,r,l) for(ll i = r; i >= l; i--)
//#define LOCAL
using namespace std;
typedef long long ll;
const ll mx = 1e5 + 10;
char s[mx];
ll l[mx], r[mx];
void solve(){
scanf("%s", s+1);
ll len = strlen(s+1);
ll ans = 0;
rep(i,0,25){
char c = i+'a';
ll zuo = 0, you = len + 1;
rep(j,1,len){
if(s[j]!=c)continue;
l[j] = zuo;
zuo = j;
}
irep(j,len,1){
if(s[j]!=c)continue;
r[j] = you;
you = j;
}
rep(j,1,len){
if(s[j]!=c)continue;
ll ln = j-l[j]-1, rn = r[j]-j-1;
ans += (1+ln) * (1+rn);
}
}
printf("%lld\n", ans);
}
int main(){
#ifdef LOCAL
freopen("1.txt","r",stdin);
#endif
solve();
#ifdef LOCAL
fclose(stdout);
#endif
return 0;
}