Lotus and Characters
Lotus有n种字母,给出每种字母的价值以及每种字母的个数限制,她想构造一个任意长度的串。 定义串的价值为:第1位字母的价值*1+第2位字母的价值*2+第3位字母的价值*3…… 求Lotus能构造出的串的最大价值。(可以构造空串,因此答案肯定≥0)
第一行是数据组数T(0≤T≤1000)。 对于每组数据,第一行一个整数n(1≤n≤26),接下来n行,每行2个整数vali,cnti(∣vali∣,cnti≤100),分别表示第i种字母的价值和个数限制。
对于每组数据,输出一行一个整数,表示答案。
2 2 5 1 6 2 3 -5 3 2 1 1 1
35 5
题解:模拟+贪心
这道题容易忽略的一点就是负数不一定不入选。因为可以通过在前面补负数,使后面正数的系数变大。
我们将所有的元素从大到小排序,然后倒叙插入(就是先插入的系数会大),如果到某一时刻答案变小,就停止。
最后输出峰值即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 10000
using namespace std;
int n,a[N];
int cmp(int x,int y)
{
return x>y;
}
int main()
{
freopen("a.in","r",stdin);
freopen("std.out","w",stdout);
int T; scanf("%d",&T);
for (int t=1;t<=T;t++) {
scanf("%d",&n);
int cnt=0;
for (int i=1;i<=n;i++) {
int val,x;
scanf("%d%d",&val,&x);
for (int j=1;j<=x;j++) a[++cnt]=val;
}
sort(a+1,a+cnt+1,cmp);
int sum=0; int ans=0; int mx=0;
for (int i=1;i<=cnt;i++) {
ans+=a[i]+sum;
sum+=a[i];
if (ans<mx) break;
mx=ans;
}
printf("%d\n",mx);
}
}
Lotus and Horticulture
这几天Lotus对培养盆栽很感兴趣,于是她想搭建一个温室来满足她的研究欲望。 Lotus将所有的n株盆栽都放在新建的温室里,所以所有盆栽都处于完全相同的环境中。 每一株盆栽都有一个最佳生长温度区间[l,r],在这个范围的温度下生长会生长得最好,但是不一定会提供最佳的研究价值(Lotus认为研究发育不良的盆栽也是很有研究价值的)。 Lotus进行了若干次试验,发现若第i株盆栽的生长温度适宜,可以提供ai的研究价值;若生长温度超过了适宜温度的上限,能提供bi的研究价值;若生长温度低于适宜温度的下限,则能提供ci的研究价值。 现在通过试验,Lotus已经得知了每一株盆栽的适宜生长温度范围,也知道了它们的a、b、c的值。你需要根据这些信息,给温室选定一个温度(这个温度可以是任意实数),使得Lotus能获得的研究价值最大。
多组数据,第一行一个整数T表示数据组数 每组数据第一行一个整数n∈[1,50000],表示盆栽数量 接下来n行每行五个整数li,ri,ai,bi,ci∈[1,109],意义如上所述
每组数据输出一行一个整数表示答案
1 5 5 8 16 20 12 10 16 3 13 13 8 11 13 1 11 7 9 6 17 5 2 11 20 8 5
83
当时写的线段树,TLE了
其实差分就可以。我们对于每个植物维护四个时间点,区间的左右端点,和左端点-0.5,右端点+0.5.
将所有的时间*2,就可以将所有的实数变成小数。
然后进行离散化,维护一个tr数组。设初始时的温度为-INF,那么此时的答案就是sigma ci
如果当前到达了一个区间的左端点,那么对总答案的影响是+(ai-ci)
如果到达区间右端点+0.5,那么对总答案的影响是+(bi-ai)
所有我们将所有的影响统计到tr数组中,那么tr数组的前缀和就是这个温度的答案。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 500003
#define LL long long
using namespace std;
int n,m,x[N],y[N],q[N],a[N],b[N],c[N];
LL val[N];
int main()
{
int T; scanf("%d",&T);
for (int t=1;t<=T;t++) {
memset(val,0,sizeof(val));
scanf("%d",&n);
int cnt=0;
for (int i=1;i<=n;i++) {
scanf("%d%d%d%d%d",&x[i],&y[i],&a[i],&b[i],&c[i]);
x[i]*=2; y[i]*=2;
q[++cnt]=x[i]; q[++cnt]=y[i]; q[++cnt]=x[i]-1; q[++cnt]=y[i]+1;
}
sort(q+1,q+cnt+1);
cnt=unique(q+1,q+cnt+1)-q-1;
LL ans=0;
for (int i=1;i<=n;i++) {
x[i]=lower_bound(q+1,q+cnt+1,x[i])-q;
y[i]=lower_bound(q+1,q+cnt+1,y[i])-q;
val[x[i]]+=(LL)(a[i]-c[i]);
val[y[i]+1]+=(LL)(b[i]-a[i]);
ans+=(LL)c[i];
}
LL mx=ans;
for (int i=1;i<=cnt;i++) {
val[i]+=val[i-1];
mx=max(mx,ans+val[i]);
}
printf("%I64d\n",mx);
}
}
Lotus and Thermodynamics
这几天Lotus对布朗运动很感兴趣,于是她想编一个模拟程序来满足她的研究欲望。 这个程序的目的是模拟一个二维平面上一些点的无规律运动,需要支持以下几种操作: I x y : 表示在平面中出现了一个新的点(x,y),编号为平面中已有的点数+1。 M l r x y : 表示编号属于[l,r]的点进行了位移(x,y)。 R l r x y a : 表示编号属于[l,r]的点关于点(x,y)逆时针旋转了角度a。其中a表示为弧度制,且a仅包含一位小数。 F l r x y d : 表示编号属于[l,r]的点以点(x,y)为中心缩放d倍,保证d∈[0,1]且d仅包含一位小数。 Q id : 询问编号为id的点的坐标,输出一行两个实数,用一个空格分开,用floor()取整到个位。即假如答案是x,y,就用printf("%.0lf %.0lf\n",floor(x),floor(y))来输出。
多组数据,第一行一个整数T表示数据组数。 每组数据第一行一个整数q∈[1,100000],表示操作个数 接下来q行,每行描述一个操作,格式如上所述 对于所有出现在输入文件里的数,保证它们属于[−1000,1000] 保证q>10000的数据不超过2组。
对于每个Q操作,用上面所述方法输出答案。保证答案中点的坐标绝对值小于107。
2 6 I 4 -1 I 8 3 R 1 1 -4 8 -0.4 Q 1 F 1 2 -1 1 0.1 I -1 9 5 I 0 4 R 1 1 -6 9 1.9 Q 1 R 1 1 1 8 2.4 Q 1
-1 -4 -4 16 -2 -1
题解:线段树+矩阵
就是对于每个点维护一个矩阵,然后每次修改相当于乘上一个矩阵
对于一个点我们维护<sx,sy,1>,其中sx,sy是点的横纵坐标。
平移操作(x,y) 可以得到<sx+x,sy+y,1> 那么区间的标记矩阵为
1 0 0
0 1 0
x y 1
放缩操作(x,y) 可以得到<x+(sx-x)*d,y+(sy-y)*d,1>,那么区间的标记矩阵为
d 0 0
0 d 0
x-dx y-dy 1
旋转操作(x,y) 可以得到<(sx-x)*cos-(sy-y)*sin+x,(sx-x)*sin+(sy-y)*cos+y,1> 那么区间的标记矩阵为
cos sin 0
-sin cos 0
-xcos+ysin+x -xsin-ycos+y 1
然后问题就变成了线段树的区间修改点查询
但是这道题的精度貌似有些问题,所有目前没有人可以A掉。。。
这里的思路和代码仅供参考。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 100003
using namespace std;
struct matrix{
double b[4][4];
};
struct data {
matrix a,delta;
}tr[N*4];
double e[4][4];
int n;
struct node {
int opt,l,r,id;
double x,y,val;
}a[N];
void clear(matrix &a)
{
for (int i=1;i<=3;i++)
for (int j=1;j<=3;j++) a.b[i][j]=0;
for (int i=1;i<=3;i++) a.b[i][i]=1;
}
void pointchange(int now,int l,int r,int x,double px,double py)
{
if (l==r) {
tr[now].a.b[1][1]=px;
tr[now].a.b[1][2]=py;
tr[now].a.b[1][3]=1;
clear(tr[now].delta);
//cout<<now<<" "<<px<<" "<<py<<endl;
//for (int i=1;i<=3;i++) printf("%.0lf ",tr[now].a.b[1][i]);
//cout<<endl;
return;
}
int mid=(l+r)/2;
clear(tr[now].delta);
if (x<=mid) pointchange(now<<1,l,mid,x,px,py);
else pointchange(now<<1|1,mid+1,r,x,px,py);
}
matrix mul(matrix a,matrix b)
{
matrix c;
for (int i=1;i<=3;i++)
for (int j=1;j<=3;j++){
c.b[i][j]=0;
for (int k=1;k<=3;k++)
c.b[i][j]+=a.b[i][k]*b.b[k][j];
}
return c;
}
bool check(matrix a)
{
for (int i=1;i<=3;i++)
for (int j=1;j<=3;j++)
if (a.b[i][j]!=e[i][j]) return true;
return false;
}
void pushdown(int now)
{
if (check(tr[now].delta)) {
tr[now<<1].a=mul(tr[now<<1].a,tr[now].delta);
tr[now<<1|1].a=mul(tr[now<<1|1].a,tr[now].delta);
tr[now<<1].delta=mul(tr[now<<1].delta,tr[now].delta);
tr[now<<1|1].delta=mul(tr[now<<1|1].delta,tr[now].delta);
clear(tr[now].delta);
}
}
void query(int now,int l,int r,int ll,int rr,matrix t)
{
if (ll<=l&&r<=rr) {
//for (int i=1;i<=3;i++) cout<<tr[now].a.b[1][i]<<" ";
//cout<<endl;
tr[now].a=mul(tr[now].a,t);
tr[now].delta=mul(tr[now].delta,t);
return;
}
int mid=(l+r)/2;
pushdown(now);
if (ll<=mid) query(now<<1,l,mid,ll,rr,t);
if (rr>mid) query(now<<1|1,mid+1,r,ll,rr,t);
}
data find(int now,int l,int r,int x)
{
if (l==r) return tr[now];
int mid=(l+r)/2;
pushdown(now);
if (x<=mid) return find(now<<1,l,mid,x);
else return find(now<<1|1,mid+1,r,x);
}
int main()
{
freopen("a.in","r",stdin);
freopen("my.out","w",stdout);
int T; scanf("%d",&T);
for (int i=1;i<=3;i++) e[i][i]=1;
for (int t=1;t<=T;t++) {
scanf("%d",&n);
int cnt=0;
for (int i=1;i<=n;i++) {
char s[3]; scanf("%s",s);
if (s[0]=='I') {
a[i].opt=1;
scanf("%lf%lf",&a[i].x,&a[i].y);
++cnt;
}
if (s[0]=='M') {
a[i].opt=2;
scanf("%d%d%lf%lf",&a[i].l,&a[i].r,&a[i].x,&a[i].y);
}
if (s[0]=='R') {
a[i].opt=3;
scanf("%d%d%lf%lf%lf",&a[i].l,&a[i].r,&a[i].x,&a[i].y,&a[i].val);
}
if (s[0]=='F') {
a[i].opt=4;
scanf("%d%d%lf%lf%lf",&a[i].l,&a[i].r,&a[i].x,&a[i].y,&a[i].val);
}
if (s[0]=='Q') {
a[i].opt=5;
scanf("%d",&a[i].id);
}
}
int now=0;
for (int i=1;i<=n;i++) {
if (a[i].opt==1) now++,pointchange(1,1,cnt,now,a[i].x,a[i].y);
if (a[i].opt==2) {
matrix t;
t.b[1][1]=1; t.b[1][2]=0; t.b[1][3]=0;
t.b[2][1]=0; t.b[2][2]=1; t.b[2][3]=0;
t.b[3][1]=a[i].x; t.b[3][2]=a[i].y; t.b[3][3]=1;
query(1,1,cnt,a[i].l,a[i].r,t);
}
if (a[i].opt==3) {
matrix t;
t.b[1][1]=cos(a[i].val); t.b[1][2]=sin(a[i].val); t.b[1][3]=0;
t.b[2][1]=-sin(a[i].val); t.b[2][2]=cos(a[i].val); t.b[2][3]=0;
t.b[3][1]=-a[i].x*cos(a[i].val)+a[i].y*sin(a[i].val)+a[i].x;
t.b[3][2]=-a[i].x*sin(a[i].val)-a[i].y*cos(a[i].val)+a[i].y;
t.b[3][3]=1;
query(1,1,cnt,a[i].l,a[i].r,t);
}
if (a[i].opt==4) {
matrix t;
t.b[1][1]=a[i].val; t.b[1][2]=0; t.b[1][3]=0;
t.b[2][1]=0; t.b[2][2]=a[i].val; t.b[2][3]=0;
t.b[3][1]=a[i].x-a[i].val*a[i].x;
t.b[3][2]=a[i].y-a[i].val*a[i].y;
t.b[3][3]=1;
query(1,1,cnt,a[i].l,a[i].r,t);
}
if (a[i].opt==5) {
data t=find(1,1,cnt,a[i].id);
printf("%.0lf %.0lf\n",floor(t.a.b[1][1]),floor(t.a.b[1][2]));
}
}
}
}