E. The Untended Antiquity

time limit per test 2 seconds
memory limit per test 512 megabytes
input standard input
output standard output

Koyomi is helping Oshino, an acquaintance of his, to take care of an open space around the abandoned Eikou Cram School building, Oshino’s makeshift residence.

The space is represented by a rectangular grid of n × m cells, arranged into n rows and m columns. The c-th cell in the r-th row is denoted by (r, c).

Oshino places and removes barriers around rectangular areas of cells. Specifically, an action denoted by “1 $r_1$ $c_1$ $r_2$ $c_2$” means Oshino’s placing barriers around a rectangle with two corners being ($r_1$, $c_1$) and ($r_2$, $c_2$) and sides parallel to squares sides. Similarly, “2 $r_1$ $c_1$ $r_2$ $c_2$” means Oshino’s removing barriers around the rectangle. Oshino ensures that no barriers staying on the ground share any common points, nor do they intersect with boundaries of the n × m area.

Sometimes Koyomi tries to walk from one cell to another carefully without striding over barriers, in order to avoid damaging various items on the ground. “3 $r_1$ $c_1$ $r_2$ $c_2$” means that Koyomi tries to walk from ($r_1$, $c_1$) to ($r_2$, $c_2$) without crossing barriers.

And you’re here to tell Koyomi the feasibility of each of his attempts.

Input

The first line of input contains three space-separated integers n, m and q (1 ≤ n, m ≤ 2 500, 1 ≤ q ≤ 100 000) — the number of rows and columns in the grid, and the total number of Oshino and Koyomi’s actions, respectively.

The following q lines each describes an action, containing five space-separated integers t, $r_1$, $c_1$, $r_2$, $c_2$ (1 ≤ t ≤ 3, 1 ≤ $r_1$, $r_2$ ≤ n, 1 ≤ $c_1$, $c_2$ ≤ m) — the type and two coordinates of an action. Additionally, the following holds depending on the value of t:

If t = 1: 2 ≤ $r_1$ ≤ $r_2$ ≤ n - 1, 2 ≤ $c_1$ ≤ $c_2$ ≤ m - 1;
If t = 2: 2 ≤ $r_1$ ≤ $r_2$ ≤ n - 1, 2 ≤ $c_1$ ≤ $c_2$ ≤ m - 1, the specified group of barriers exist on the ground before the removal.
If t = 3: no extra restrictions.

Output

For each of Koyomi’s attempts (actions with t = 3), output one line — containing “Yes” (without quotes) if it’s feasible, and “No” (without quotes) otherwise.

Examples

input

1
2
3
4
5
6
5 6 5
1 2 2 4 5
1 3 3 3 3
3 4 4 1 1
2 2 2 4 5
3 1 1 4 4

output

1
2
No
Yes

input

1
2
3
4
5
6
7
8
9
2500 2500 8
1 549 1279 1263 2189
1 303 795 1888 2432
1 2227 622 2418 1161
3 771 2492 1335 1433
1 2017 2100 2408 2160
3 48 60 798 729
1 347 708 1868 792
3 1940 2080 377 1546

output

1
2
3
No
Yes
No

Solution

二维线段树+set/vector/rand

二维数状数组+rand+’+’

二维数状数组+rand+’^’

官方解答

我读官方解答读下来,发现官方解答用的是一维线段树 只在左右方向进行划分,对于横坐标划分后保存 纵向的 启始和结束以及_id 这样看得话_id是否有点多余??? 但好像写出来比比较 _u_d 看上去简洁 不过这个都不影响复杂度,然后我尝试了把 _u_d进行编码 当作返回,结论是 不可以的,因为 可能目标两个的点所在的矩形 不是同一个,但 这两个矩形的上下的分化是一样的:-)僵硬,结论还是要_id

我反正还没想到2D的线段树也就是 四叉树 加信息标注 要怎么做???? need help 上面三个选手的代码都是带rand()

然后官方题解用了 好多C++新的东西 比如 auto and 低头

以及看别人的代码发现 手工编码解码很少了,大家都用的makepair 甚至两重makepair

F. Yet Another Minimization Problem

time limit per test 2 seconds
memory limit per test 256 megabytes
input standard input
output standard output

You are given an array of n integers $a_1$ ... $a_n$. The cost of a subsegment is the number of unordered pairs of distinct indices within the subsegment that contain equal elements. Split the given array into k non-intersecting non-empty subsegments so that the sum of their costs is minimum possible. Each element should be present in exactly one subsegment.

Input

The first line contains two integers n and k ($2$ ≤ n ≤ $10^5$, 2 ≤ k ≤ min (n, 20)) — the length of the array and the number of segments you need to split the array into.

The next line contains n integers $a_1$, $a_2$, …, $a_n$ (1 ≤ $a_i$ ≤ n) — the elements of the array.

Output

Print single integer: the minimum possible total cost of resulting subsegments.

Examples

input

1
2
7 3
1 1 3 3 3 2 1

output

1
1

input

1
2
10 2
1 2 1 2 1 2 1 2 1 2

output

1
8

input

1
2
13 3
1 2 2 2 1 2 1 1 1 2 2 1 1

output

1
9

Note

In the first example it’s optimal to split the sequence into the following three subsegments: [1], [1, 3], [3, 3, 2, 1]. The costs are 0, 0 and 1, thus the answer is 1.

In the second example it’s optimal to split the sequence in two equal halves. The cost for each half is 4.

In the third example it’s optimal to split the sequence in the following way: [1, 2, 2, 2, 1], [2, 1, 1, 1, 2], [2, 1, 1]. The costs are 4, 4, 1.


Solution

我开始还以为我做出来了,然而第6个点就爆了。下面用|表示分割_表示数字

我的最开始的想法是先随意将原数组随意分割为k组______|____|_________|__________

然后对每一个分割进行左右调整,直到不可调为止,______←|→____|_________|__________,但这样局部最优并不能达到全局最优

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
long long costn(long long n){
return (n-1)*n/2;
}
long long cost[100010]={0};
void init(){
int i;
for(i=0;i<=100000;i++)
cost[i]=costn(i);
}

int n,k;
long long ans = 0;

long long v[100010]={0};
long long cnt[100010]={0};
long long cntnow[100010]={0};

int divk[30]={0}; // return index

void clear(){
int i;
for(i=0;i<=n;i++){
cnt[i]=0;
cntnow[i]=0;
}
}

bool doaj(int index){
clear();
int l = index == 0?0:divk[index-1]+1;
int r = index == k-1?n-1:divk[index+1];
// cout<<index<<":"<<l<<","<<r<<endl;
int i;
for(i=l;i<=r;i++){
cnt[v[i]]++;
// cout<<v[i]<<" "<<cnt[v[i]]<<endl;
}

int ansi = l;
long long dermin = 100000000000;
long long dernow = 0;
long long derori = 100000000000;
for(i=l;i<r;i++){
cntnow[v[i]]++;
long long oril = cntnow[v[i]]-1;
long long orir = cnt[v[i]] - oril;
long long oriv = cost[oril]+cost[orir];

long long nowl = oril+1;
long long nowr = orir-1;
long long nowv = cost[nowl]+cost[nowr];

dernow += -oriv+nowv;
if(i == divk[index]){
derori = dernow;
}
if(dernow < dermin || (dernow==dermin && i==divk[index])){
dermin = dernow;
ansi = i;
}
}
if(dermin < derori){
if(ansi != divk[index]){
// cout<<index<<": ["<<l<<","<<r<<"]"<<"der:"<<dermin-derori<<" | "<<divk[index]<<" -> "<<ansi<<endl;
divk[index] = ansi;
ans += dermin-derori;
return true;
}
}
return false;
}

int main(){
init();
cin>>n>>k;
k--;
int i;
for(i=0;i<n;i++)
scanf("%lld",&v[i]);

for(i=0;i<k;i++)
divk[i]=i;

for(i=k;i<n;i++){
cnt[v[i]]++;
}

for(i=1;i<=n;i++){
ans += cost[cnt[i]];
}

bool adjust=true;

while(adjust){
adjust=false;
for(i=0;i<k;i++){
if(doaj(i))
adjust=true;
}
}

cout<<ans<<endl;
return 0;
}

下一个想法是动态规划,dp[p][k]返回把[0 , p-1]分为k组的最小代价,则答案为dp[n][k]

其中再进行划分k组[0 , p-1] -> k-1组[0 , j-1] + 1组[j,p-1]

dp[p][k] = min{dp[j][k-1] + cost[j,p-1]}

有了这个 时间复杂度在接近 $O(n^3)$ , 对一个固定的k遍历p需要n,对一个p遍历j需要n,对一个j计算cost[j,p-1]需要n

分析:

k遍历p 最外层难优化

考虑最里层cost[j,p-1] 因为相邻的j的访问 会使这个函数左右范围变化不大,所以如果能用全局或者静态变量来维护左、右指向以及和,就能对这里的时间复杂度降低到O(1)

1
2
3
4
5
6
7
8
9
10
static long long cost(int l,int r){
static int _l = 0;
static int _r = -1;
static long long _ans = 0;
while(_r < r) _ans += cnt[v[++_r]]++;
while(_l > l) _ans += cnt[v[--_l]]++;
while(_r > r) _ans -= --cnt[v[_r--]];
while(_l < l) _ans -= --cnt[v[_l++]];
return _ans;
}

这样总的时间复杂度还是在O(n^2)

如果可以对一个p 我们的j的范围不再是[1~p-1],而能更小,那么时间复杂度也就还能下降

下面假设对给定p最小的分割为m,也就是dp[p][k]的最小值为dp[m][k-1] + cost[m,p-1]

_____________m-1|m_________p-1|p___________

______n-1|n_____|__________p-1|p_____|_____

______n-1|n_____|_____________|___q-1|q____

对于一个q>p 最小的分割为n,也就是dp[q][k]最小值为dp[n][k-1] + cost[n,q-1]

1
2
3
4
5
dp[n][k-1] + cost[n,q-1]
= dp[n][k-1] + cost[n,p-1] + der[n->q)[p->q)
>= dp[p][k] + der[n->q)[p->q)
= dp[m][k-1]+cost[m,p-1] + der[n->p)[p->q)
>= dp[m][k-1]+cost[m,p-1] + der[m->p)[p->q)

以上,其中der[base][add]表示在base的基础上再增加add部分的 新增加的cost

即是 在m左侧的最终划分都>=m处的划分,因此 如果在p计算出了m,之后再计算q的分割点时遍历只需要从m->q

同理可证当q<p时 更小的值只会在m左侧

因此 有了这个关系 就可以进行二分搜索,时间复杂度也就降到了O(n log n) [好像也不完全是个这个 估计比这个大一点 因为这样二分以后cost函数的均摊就不是O(1)的样子了]

实现如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#define MAX 10000000000

using namespace std;
long long minn(long long v1,long long v2){return v1<v2?v1:v2;}
long long maxx(long long v1,long long v2){return v1>v2?v1:v2;}

long long v[100010]={0};
long long cnt[100010]={0};
long long dp[100010][30]={0};

int n,k;

static long long cost(int l,int r){
static int _l = 0;
static int _r = -1;
static long long _ans = 0;
while(_r < r) _ans += cnt[v[++_r]]++;
while(_l > l) _ans += cnt[v[--_l]]++;
while(_r > r) _ans -= --cnt[v[_r--]];
while(_l < l) _ans -= --cnt[v[_l++]];
// cout<<"["<<_l<<","<<_r<<"]"<<_ans<<endl;
return _ans;
}

void solve(const int & kk,int l,int r,int mathl,int mathr){
// cout<<"---------------:"<<l<<" "<<r<<" "<<mathl<<" "<<mathr<<" "<<endl;
if(l > r)
return ;
int j = (l+r)/2;
int min_pos = mathl;
dp[j][kk] = MAX;
int maxi = minn(j,mathr);
int starti = maxx(kk-1,mathl);
int i;
for(i=starti;i<=maxi;i++){
long long newv = dp[i][kk-1] + cost(i,j-1);
// cout<<l<<" "<<r<<" "<<j<<" "<<i<<" "<<newv<<endl;
if(newv < dp[j][kk]){
dp[j][kk] = newv;
min_pos = i;
}
}
solve(kk, l , j-1, mathl , min_pos);
solve(kk, j+1, r , min_pos, mathr);
}

int main(){
cin>>n>>k;
int i,j,o;
for(i=0;i<n;i++)
scanf("%lld",&v[i]);

dp[0][1] = 0;
for(i=1;i<=n;i++)dp[i][1] = cost(0,i-1);

for(i=2;i<=k;i++)
solve(i,1,n,1,n);
cout<<dp[n][k]<<endl;

return 0;
}

AC

DP Optimizations

F - Best Representation

给小写字母字符串S

问S能最少被切割成多少个(?),使得每个子串都不能表示成循环节(ababa好,ababab坏)

有多少个方案 能 达到最小的切割数 mod 1e9+7

|S| 5e5

2s

256mb

我的思路

如果整个字符串是好的,那么答案为1,1

否则 整个字符串 如果是坏的,那么它可以表示成 字符串t的重复拼接

那么 最小循环节 长度如果 > 1,那么删去最后一个 是否是一个方案呢??

1
2
3
[.....][.....][.....][.....][.....][.....]
[...][...][...][...][...][...][...][...]
x

注意到这个两个数差为1,所以gcd(len)=1

而它们相互间 多个不同偏移量的对应相等,将会像gcd过程一样对位相等

所以不可能

所以 最小分割一定是2


所以问题变成了,整个字符串有多少个切割让 left right 都是好的

同样的, 只要不是最小切割的倍数即可


所以感觉就过了?

还是有一点点问题


1
2
3
111222111222
xx
yyyyyyyyyy

对于S的最小循环节 内还是有可能有更小的 循环的存在的

判断也好判断,如果要长度len的 循环节长度是cycle,那么len-cycle的循环节的长度是cycle的因数,注意前缀后缀都要算


然而 https://atcoder.jp/contests/arc060/submissions/50471607

ACx63,WAx2

subtask1_03.txt 和 subtask2_01.txt 炸了


1
2
3
4
5
6
7
abaababaab  
len(s) = 10, cycle size = 5
brute force = 8
left cycle, right not cycle, [0,5][6,9]
abaaba
2
9

这样的话虽然 baab是好的,但是左边是坏的且超过了单个循环节的长度

閱讀全文 »

F - Unhappy Hacking

https://atcoder.jp/contests/arc059/tasks/arc059_d

操作 push(0),push(1),pop(),其中pop在空时也可以操作

给定0/1串,问有多少不同n次的操作序列 能得到s, 方案数mod1e9+7

n 5000

2s

256mb

我的思路

对于 开头 需要计算 多少次可以在空时pop的操作 得到长度0

对于 中间 需要计算 多少次不可以在空时pop的操作 得到长度0

那么 用生成函数表示

$[x^t]g_0(x)$ 表示 $t$次操作长度0的第一种操作

$[x^t]f_0(x)$ 表示 $t$次操作长度0的第二种操作

那么有$ans = [x^{n}] g_0(x) (\cdot x \cdot f_0(x))^{|s|}$

$= [x^{n}] g_0(x) \cdot x^{|s|} \cdot f_0(x)^{|s|}$

$= [x^{n-|s|}] g_0(x) \cdot f_0(x)^{|s|}$

后面直接多项式快速幂就好了,1e9+7 原根太小,没法ntt

閱讀全文 »
0%