結果

問題 No.426 往復漸化式
ユーザー 37zigen
提出日時 2016-09-30 01:14:13
言語 Java
(openjdk 23)
結果
AC  
実行時間 1,548 ms / 5,000 ms
コード長 8,174 bytes
コンパイル時間 5,041 ms
コンパイル使用メモリ 88,552 KB
実行使用メモリ 114,364 KB
最終ジャッジ日時 2024-11-21 10:56:10
合計ジャッジ時間 19,583 ms
ジャッジサーバーID
(参考情報)
judge1 / judge5
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 1
other AC * 22
権限があれば一括ダウンロードができます

ソースコード

diff #
プレゼンテーションモードにする

package No400;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Comparator;
public class Q426 {
public static void main(String[] args) {
new Q426().run();
}
final long MOD = 1_000_000_000 + 7;
static InputStream is;
static PrintWriter out;
static String INPUT = "";
void run() {
is = INPUT.isEmpty() ? System.in : new ByteArrayInputStream(INPUT.getBytes());
out = new PrintWriter(System.out);
solver();
out.flush();
}
void solver() {
int n = ni();
long[][] a_0 = { { nl() }, { nl() }, { nl() } };
long[][] b_n = { { nl() }, { nl() } };
int q = ni();
String[] s = new String[q];
int[][] x = new int[q][];
int[] shrink = new int[q];
long[][][]as = new long[ q][][];
long[][][] bs = new long[q][][];
for (int i = 0; i < q; i++) {
s[i] = ns();
shrink[i] = ni();
x[i] = new int[] { shrink[i], i };
if (s[i].equals("a")) {
as[i] = new long[][] { { nl(), nl(), nl() }, { nl(), nl(), nl() }, { nl(), nl(), nl() } };
} else if (s[i].equals("b")) {
bs[i] = new long[][] { { nl(), nl() }, { nl(), nl() } };
}
}
Arrays.sort(x, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return Integer.compare(o1[0], o2[0]);
}
});
int pos = -1;
int[] ref = new int[2 * q + 1];
Arrays.fill(ref, -1);
for (int i = 0; i < q; i++) {
if (i == 0 || x[i][0] != x[i - 1][0]) {
if (i == 0 && x[i][0] != 0)
pos += 2;
else if (i == q - 1 && x[i][0] != n)
pos += 2;
else if (i != 0 && x[i][0] != x[i - 1][0] + 1)
pos += 2;
else if (i == 0 && x[i][0] == 0)
pos += 1;
else if (i != 0 && x[i][0] != x[i - 1][0])
pos += 1;
}
shrink[x[i][1]] = pos;
ref[pos] = x[i][0];
}
if (x[q - 1][0] != n)
pos++;
pos++;
ref = Arrays.copyOf(ref, pos);
SegmentTree seg = new SegmentTree(Arrays.copyOf(ref, pos), n);
for (int i = 0; i < q; i++) {
if (s[i].equals("a")) {
seg.set(shrink[i], as[i], 0);
} else if (s[i].equals("b")) {
seg.set(shrink[i], bs[i], 1);
} else if (s[i].equals("ga")) {
print(seg.geta(i, a_0, shrink));
} else if (s[i].equals("gb")) {
if (shrink[i] == pos - 1) {
print(b_n);
} else
print(seg.getb(i, a_0, b_n, shrink));
}
}
}
void print(long[][] a){
for(int i=0;i<a.length;i++){
System.out.print(a[i][0]+(i==a.length-1?"\n":" "));
}
}
class SegmentTree {
int n = 1;
long[][][][] node;
public SegmentTree(int[] ref, int N) {
int n_ = ref.length;
while (n < n_)
n *= 2;
node = new long[2 * n - 1][3][][];
for (int i = 0; i < 2 * n - 1; i++) {
node[i][0] = new long[][] { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } };
node[i][1] = new long[][] { { 1, 0 }, { 0, 1 } };
}
for (int i = 0; i < n_; i++) {
if (ref[i] == -1) {
int post = (i == n_ - 1 ? N + 1 : ref[i + 1]);
int pre = (i == 0 ? -1 : ref[i - 1]);
node[i + n - 1][2] = init(pre + 1, post - 1);
} else {
node[i + n - 1][2] = init(ref[i], ref[i]);
}
}
for (int i = n - 2; i >= 0; i--) {
node[i][2] = merge(node[2 * i + 1], node[2 * i + 2])[2];
}
}
long[][] init(long a, long b) {
long sum1 = (b - a + 1) % MOD * (b + a) % MOD * inv2 % MOD;
long sum2 = b - a + 1;
return new long[][] { { 6L * sum1, 6L * sum1 + 1 * sum2, 6L * sum1 + 2 * sum2 },
{ 6L * sum1 + 3L * sum2, 6L * sum1 + 4L * sum2, 6L * sum1 + 5L * sum2 } };
}
void set(int k, long[][] val, int mode) {
k += n - 1;
node[k][mode] = val;
while (k > 0) {
k = (k - 1) / 2;
node[k] = merge(node[2 * k + 1], node[2 * k + 2]);
}
}
long[][][] query(int a, int b) {
return query(a, b, 0, n, 0);
}
long[][][] query(int a, int b, int l, int r, int k) {
if (r <= a || b <= l) {
return new long[][][] { { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } }, { { 1, 0 }, { 0, 1 } }, null };
} else if (a <= l && r <= b) {
return node[k];
} else {
long[][][] vl = query(a, b, l, (l + r) / 2, 2 * k + 1);
long[][][] vr = query(a, b, (l + r) / 2, r, 2 * k + 2);
return merge(vl, vr);
}
}
long[][][] merge(long[][][] vl, long[][][] vr) {
long[][][] ret = new long[][][] { mul(vr[0], vl[0]), mul(vl[1], vr[1]), null };
if (vl[2] == null && vr[2] == null)
ret[2] = null;
else if (vl[2] == null)
ret[2] = vr[2];
else if (vr[2] == null)
ret[2] = vl[2];
else
ret[2] = sum(vl[2], mul(mul(vl[1], vr[2]), vl[0]));
return ret;
}
long[][] geta(int i, long[][] a_0, int[] shrink) {
return mul(query(0, shrink[i] - 1 + 1)[0], a_0);
}
long[][] getb(int i, long[][] a_0, long[][] b_n, int[] shrink) {
return sum(mul(query(shrink[i] + 1, n + 1)[1], b_n),
mul(mul(query(shrink[i]+1, n + 1)[2], query(0, shrink[i] + 1)[0]), a_0));
}
}
long[][] sum(long[][] A, long[][] B) {
long[][] C = new long[A.length][A[0].length];
for (int i = 0; i < A.length; i++) {
for (int j = 0; j < A[0].length; j++) {
C[i][j] = (A[i][j] % MOD + B[i][j] % MOD) % MOD;
}
}
return C;
}
long[][] mul(long[][] A, long[][] B) {
long[][] C = new long[A.length][B[0].length];
for (int i = 0; i < A.length; i++) {
for (int j = 0; j < B[0].length; j++) {
for (int k = 0; k < A[0].length; k++) {
C[i][j] += A[i][k] % MOD * B[k][j] % MOD;
C[i][j] %= MOD;
}
}
}
return C;
}
long inv2 = inv(2, MOD);
long inv(long a, long mod) {
a = a % mod;
long b = mod;
long p = 1, q = 0;
while (b > 1) {
long c = b / a;
b = b % a;
q = q - p * c;
long d = b;
b = a;
a = d;
d = p;
p = q;
q = d;
}
while (q < 0)
q += mod;
return q;
}
static long nl() {
try {
long num = 0;
boolean minus = false;
while ((num = is.read()) != -1 && !((num >= '0' && num <= '9') || num == '-'))
;
if (num == '-') {
num = 0;
minus = true;
} else {
num -= '0';
}
while (true) {
int b = is.read();
if (b >= '0' && b <= '9') {
num = num * 10 + (b - '0');
} else {
return minus ? -num : num;
}
}
} catch (IOException e) {
}
return -1;
}
static char nc() {
try {
int b = skip();
if (b == -1)
return 0;
return (char) b;
} catch (IOException e) {
}
return 0;
}
static double nd() {
try {
return Double.parseDouble(ns());
} catch (Exception e) {
}
return 0;
}
static String ns() {
try {
int b = skip();
StringBuilder sb = new StringBuilder();
if (b == -1)
return "";
sb.append((char) b);
while (true) {
b = is.read();
if (b == -1)
return sb.toString();
if (b <= ' ')
return sb.toString();
sb.append((char) b);
}
} catch (IOException e) {
}
return "";
}
public static char[] ns(int n) {
char[] buf = new char[n];
try {
int b = skip(), p = 0;
if (b == -1)
return null;
buf[p++] = (char) b;
while (p < n) {
b = is.read();
if (b == -1 || b <= ' ')
break;
buf[p++] = (char) b;
}
return Arrays.copyOf(buf, p);
} catch (IOException e) {
}
return null;
}
public static byte[] nse(int n) {
byte[] buf = new byte[n];
try {
int b = skip();
if (b == -1)
return null;
is.read(buf);
return buf;
} catch (IOException e) {
}
return null;
}
static int skip() throws IOException {
int b;
while ((b = is.read()) != -1 && !(b >= 33 && b <= 126))
;
return b;
}
static boolean eof() {
try {
is.mark(1000);
int b = skip();
is.reset();
return b == -1;
} catch (IOException e) {
return true;
}
}
static int ni() {
try {
int num = 0;
boolean minus = false;
while ((num = is.read()) != -1 && !((num >= '0' && num <= '9') || num == '-'))
;
if (num == '-') {
num = 0;
minus = true;
} else {
num -= '0';
}
while (true) {
int b = is.read();
if (b >= '0' && b <= '9') {
num = num * 10 + (b - '0');
} else {
return minus ? -num : num;
}
}
} catch (IOException e) {
}
return -1;
}
void tr(Object... objects) {
System.out.println(Arrays.deepToString(objects));
}
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
0