D: タコヤキオイシクナール - AtCoder Regular Contest 008 | AtCoder
問題概略
N個の箱が一列に繋がって並んでおり、それらは実数(a,b)を持つ。
箱に数字を渡すとその数字は a * 渡された数 + bに変化して次の箱に渡される。
(a,b)は(1,0)で初期化されているが、M回値の更新が行われる
1を渡した時、すべての状態における結果の最大値と最小値を求めよ
制約
pi (1≦pi≦N) ボックス番号
1≦N≦1012, 0≦M≦100,000
ai (−1≦ai≦1)、b の値を表す実数 bi (−1≦bi≦1)
解法
隣り合う2つの演算(a,b),(c,d)は(a * c , b * c + d)で一つにまとめられるためセグメント木を使えば良い。求めたい区間は端から端で固定されているため、一番上の値を返せばよくO(1)で求められ、アップデートはO(long n)で行ける。
また、Nがやばい大きい事と、(1,0)は答えに影響を与えないのでM個のボックスがある問題だとみなせる。
longの箱の場所とそれが与えられた中で前から何番目かを紐付ければ解ける。
class SegmentTakoyaki
{
double[] a, b;
int N;
SegmentTakoyaki(int n)
{
N = 1;
while (n > N) N *= 2;
a = new double[N * 2];
b = new double[N * 2];
Arrays.fill(a, 1);
Arrays.fill(b, 0);
}
public void update(int id, double av, double bv)
{
id = id + N - 1;
a[id] = av;
b[id] = bv;
while (id > 0)
{
id = (id - 1) / 2;
double la = a[id * 2 + 1];
double lb = b[id * 2 + 1];
double ra = a[id * 2 + 2];
double rb = b[id * 2 + 2];
a[id] = la * ra;
b[id] = lb * ra + rb;
}
}
public double calcTaste()
{
return a[0] + b[0];
}
}
public class Main
{
static StringBuilder sb = new StringBuilder();
static FastScanner sc = new FastScanner(System.in);
static int INF = 12345678;
static long LINF = 123456789123456789L;
static long MINF = -123456789123456789L;
static long MOD = 1000000007;
static int[] y4 = {0, 1, 0, -1};
static int[] x4 = {1, 0, -1, 0};
static int[] y8 = {0, 1, 0, -1, -1, 1, 1, -1};
static int[] x8 = {1, 0, -1, 0, 1, -1, 1, -1};
static long[] F;
static boolean[] isPrime;
static int[] primes;
static char[][] map;
static int M;
static long N;
static int[] A;
public static void main(String[] args)
{
N = sc.nextLong();
M = sc.nextInt();
if (M == 0)
{
System.out.println(1);
System.out.println(1);
return;
}
long[] p = new long[M];
double[] a = new double[M];
double[] b = new double[M];
TreeSet<Long> lindexes = new TreeSet<>();
for (int m = 0; m < M; m++)
{
p[m] = sc.nextLong() - 1;
a[m] = sc.nextDouble();
b[m] = sc.nextDouble();
lindexes.add(p[m]);
}
HashMap<Long, Integer> ltoi = new HashMap<>();
int index = 0;
for (Long lindex : lindexes)
ltoi.put(lindex, index++);
SegmentTakoyaki st = new SegmentTakoyaki(M);
double min = 1;
double max = 1;
for (int i = 0; i < M; i++)
{
int pi = ltoi.get(p[i]);
double av = a[i];
double bv = b[i];
st.update(pi,av,bv);
double score = st.calcTaste();
min = Math.min(min, score);
max = Math.max(max, score);
}
System.out.println(min);
System.out.println(max);
}