#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define fbo find_by_order
#define ook order_of_key
typedef long long ll;
typedef pair<int,int> ii;
typedef vector<int> vi;
typedef long double ld;
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> pbds;
typedef set<int>::iterator sit;
typedef map<int,int>::iterator mit;
typedef vector<int>::iterator vit;
const int C = 3;
const int BL = 800;
unsigned int B[100001][3];
struct change
{
unsigned int add,mult;
};
struct block
{
int l,r;
change mod[3][3];
unsigned int sum[3];
};
block init(int l, int r)
{
block tmp;
memset(tmp.sum,0,sizeof(tmp.sum));
////////cerr<<"SUM : "<<tmp.sum[0]<<'\n';
for(int j=0;j<3;j++)
{
for(int i=l;i<=r;i++)
{
tmp.sum[j]+=B[i][j];
//////cerr<<i<<' '<<j<<' '<<B[i][j]<<' '<<tmp.sum[j]<<' '<<l<<' '<<r<<'\n';
}
//////cerr<<l<<' '<<r<<' '<<tmp.sum[j]<<'\n';
}
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
tmp.mod[i][j].add=0;
if(i==j) tmp.mod[i][j].mult=1;
else tmp.mod[i][j].mult=0;
}
}
tmp.l=l; tmp.r=r;
return tmp;
}
list<block> vec; //linked list of blocks
typedef list<block>::iterator lit;
unsigned int queryblock(lit a, int idx)
{
return a->sum[idx];
}
void propogate(lit it) //update a for the part it
{
int l = it->l; int r = it->r;
for(int i = l; i <= r; i++)
{
unsigned int s[3];
for(int j = 0; j < 3; j++)
{
s[j]=0;
for(int k = 0; k < 3; k++)
{
s[j] += B[i][k]*it->mod[j][k].mult;
s[j] += it->mod[j][k].add;
////cerr<<it->mod[j][k].mult<<' '<<it->mod[j][k].add<<" | ";
}
////cerr<<s[j]<<' ';
////cerr<<'\n';
}
////cerr<<'\n';
for(int j=0;j<3;j++)
{
B[i][j]=s[j];
}
}
}
void recalc(int n) //recalculates the whole thing. call recalc(w)
{
for(lit it = vec.begin(); it != vec.end(); it++)
{
propogate(it);
}
vec.clear();
for(int i = 0; i < n; i+=BL)
{
int l = i; int r = min(n-1,i+BL-1);
vec.pb(init(l,r));
////////cerr<<l<<' '<<r<<'\n';
}
}
lit split(lit it, int mid) //split into [l, mid] and [mid+1, r]. returns the last position
{
int l = it->l;
int r = it->r;
propogate(it);
block a = init(l,mid);
block b = init(mid+1,r);
//////cerr<<"SUM : "<<b.sum[0]<<'\n';
lit it2 = vec.insert(it,a);
it2++;
lit it3 = vec.erase(it2);
return vec.insert(it3,b);
}
unsigned int query(int l, int r, int idx)
{
unsigned int res = 0;
for(lit it = vec.begin(); it != vec.end(); it++)
{
int L = it->l; int R = it->r;
if(L>R) continue;
if(R<l||L>r) continue;
if(l<=L&&R<=r)
{
res+=queryblock(it,idx);
}
else if(L<=l&&r<=R) //L l r R
{
//////cerr<<"HERE IT : "<<it->l<<' '<<it->r<<' '<<it->sum[idx]<<' '<<B[0][0]<<' '<<it->mod[0][0].mult<<'\n';
lit tmp = split(it,l-1);
//////cerr<<"HERE 2 : "<<tmp->l<<' '<<tmp->r<<' '<<tmp->sum[idx]<<' '<<B[0][0]<<'\n';
lit tmp2 = split(tmp,r);
tmp2--;
//////cerr<<"HERE : "<<tmp2->l<<' '<<tmp2->r<<' '<<tmp2->sum[idx]<<'\n';
it=tmp2;
res+=queryblock(it,idx);
}
else if(L<l) //L l R r
{
lit tmp = split(it,l-1);
it=tmp;
//cerr<<"L R : "<<it->l<<' '<<it->r<<' '<<res<<' '<<queryblock(it,idx)<<'\n';
res+=queryblock(it,idx);
}
else if(R>r) //l L r R
{
lit tmp = split(it,r);
tmp--;
it=tmp;
//cerr<<"L R : "<<it->l<<' '<<it->r<<' '<<res<<' '<<queryblock(it,idx)<<'\n';
res+=queryblock(it,idx);
}
else assert(0);
}
return res;
}
void copy(int l, int r, int t1, int t2)
{
for(lit it = vec.begin(); it != vec.end(); it++)
{
int L = it->l; int R = it->r;
if(L>R) continue;
if(R<l||L>r) continue;
if(l<=L&&R<=r)
{
for(int j=0;j<3;j++)
{
it->mod[t2][j]=it->mod[t1][j];
}
it->sum[t2]=it->sum[t1];
}
else if(L<=l&&r<=R) //L l r R
{
lit tmp = split(it,l-1);
lit tmp2 = split(tmp,r);
tmp2--;
it=tmp2;
for(int j=0;j<3;j++)
{
it->mod[t2][j]=it->mod[t1][j];
}
it->sum[t2]=it->sum[t1];
}
else if(L<l) //L l R r
{
lit tmp = split(it,l-1);
it=tmp;
for(int j=0;j<3;j++)
{
it->mod[t2][j]=it->mod[t1][j];
}
it->sum[t2]=it->sum[t1];
}
else if(R>r) //l L r R
{
lit tmp = split(it,r);
tmp--;
it=tmp;
for(int j=0;j<3;j++)
{
it->mod[t2][j]=it->mod[t1][j];
}
it->sum[t2]=it->sum[t1];
}
else assert(0);
}
}
void swap(int l, int r, int t1, int t2)
{
for(lit it = vec.begin(); it != vec.end(); it++)
{
int L = it->l; int R = it->r;
if(L>R) continue;
if(R<l||L>r) continue;
if(l<=L&&R<=r)
{
for(int j=0;j<3;j++)
{
swap(it->mod[t2][j],it->mod[t1][j]);
}
swap(it->sum[t2],it->sum[t1]);
}
else if(L<=l&&r<=R) //L l r R
{
lit tmp = split(it,l-1);
lit tmp2 = split(tmp,r);
tmp2--;
it=tmp2;
for(int j=0;j<3;j++)
{
swap(it->mod[t2][j],it->mod[t1][j]);
}
swap(it->sum[t2],it->sum[t1]);
}
else if(L<l) //L l R r
{
lit tmp = split(it,l-1);
it=tmp;
for(int j=0;j<3;j++)
{
swap(it->mod[t2][j],it->mod[t1][j]);
}
swap(it->sum[t2],it->sum[t1]);
}
else if(R>r) //l L r R
{
lit tmp = split(it,r);
tmp--;
it=tmp;
for(int j=0;j<3;j++)
{
swap(it->mod[t2][j],it->mod[t1][j]);
}
swap(it->sum[t2],it->sum[t1]);
}
else assert(0);
}
}
void modify(int l, int r, int t, unsigned int p1, unsigned int p2)
{
for(lit it = vec.begin(); it != vec.end(); it++)
{
int L = it->l; int R = it->r;
if(L>R) continue;
if(R<l||L>r) continue;
if(l<=L&&R<=r)
{
for(int j=0;j<3;j++)
{
//it->mod[t2][j]=it->mod[t1][j];
unsigned int a = it->mod[t][j].mult;
unsigned int b = it->mod[t][j].add;
it->mod[t][j].mult=a*p1;
it->mod[t][j].add=b*p1;
}
it->mod[t][0].add+=p2;
it->sum[t]*=p1;
it->sum[t]+=(R-L+1)*p2;
}
else if(L<=l&&r<=R) //L l r R
{
lit tmp = split(it,l-1);
lit tmp2 = split(tmp,r);
tmp2--;
it=tmp2;
for(int j=0;j<3;j++)
{
//it->mod[t2][j]=it->mod[t1][j];
unsigned int a = it->mod[t][j].mult;
unsigned int b = it->mod[t][j].add;
it->mod[t][j].mult=a*p1;
it->mod[t][j].add=b*p1;
}
it->mod[t][0].add+=p2;
it->sum[t]*=p1;
it->sum[t]+=(it->r-it->l+1)*p2;
}
else if(L<l) //L l R r
{
lit tmp = split(it,l-1);
it=tmp;
for(int j=0;j<3;j++)
{
//it->mod[t2][j]=it->mod[t1][j];
unsigned int a = it->mod[t][j].mult;
unsigned int b = it->mod[t][j].add;
it->mod[t][j].mult=a*p1;
it->mod[t][j].add=b*p1;
}
it->mod[t][0].add+=p2;
it->sum[t]*=p1;
it->sum[t]+=(it->r-it->l+1)*p2;
//cerr<<"SUM : "<<it->l<<' '<<it->r<<' '<<it->sum[t]<<'\n';
}
else if(R>r) //l L r R
{
lit tmp = split(it,r);
tmp--;
it=tmp;
for(int j=0;j<3;j++)
{
//it->mod[t2][j]=it->mod[t1][j];
unsigned int a = it->mod[t][j].mult;
unsigned int b = it->mod[t][j].add;
it->mod[t][j].mult=a*p1;
it->mod[t][j].add=b*p1;
}
it->mod[t][0].add+=p2;
it->sum[t]*=p1;
it->sum[t]+=(it->r-it->l+1)*p2;
//cerr<<"SUM : "<<it->l<<' '<<it->r<<' '<<it->sum[t]<<'\n';
}
else assert(0);
/*
propogate(it);
block tmp = init(it->l,it->r);
(*it) = tmp;
*/
}
}
void advmodify(int l, int r, int t1, int t2, unsigned int p)
{
for(lit it = vec.begin(); it != vec.end(); it++)
{
int L = it->l; int R = it->r;
if(L>R) continue;
if(R<l||L>r) continue;
if(l<=L&&R<=r)
{
it->sum[t2]+=p*it->sum[t1];
for(int j=0;j<3;j++)
{
//it->mod[t2][j]=it->mod[t1][j];
it->mod[t2][j].mult += it->mod[t1][j].mult*p;
it->mod[t2][j].add += it->mod[t1][j].add*p;
}
}
else if(L<=l&&r<=R) //L l r R
{
lit tmp = split(it,l-1);
lit tmp2 = split(tmp,r);
tmp2--;
it=tmp2;
it->sum[t2]+=p*it->sum[t1];
for(int j=0;j<3;j++)
{
//it->mod[t2][j]=it->mod[t1][j];
it->mod[t2][j].mult += it->mod[t1][j].mult*p;
it->mod[t2][j].add += it->mod[t1][j].add*p;
}
}
else if(L<l) //L l R r
{
lit tmp = split(it,l-1);
it=tmp;
it->sum[t2]+=p*it->sum[t1];
for(int j=0;j<3;j++)
{
//it->mod[t2][j]=it->mod[t1][j];
it->mod[t2][j].mult += it->mod[t1][j].mult*p;
it->mod[t2][j].add += it->mod[t1][j].add*p;
}
}
else if(R>r) //l L r R
{
lit tmp = split(it,r);
tmp--;
it=tmp;
it->sum[t2]+=p*it->sum[t1];
for(int j=0;j<3;j++)
{
//it->mod[t2][j]=it->mod[t1][j];
it->mod[t2][j].mult += it->mod[t1][j].mult*p;
it->mod[t2][j].add += it->mod[t1][j].add*p;
}
}
else assert(0);
/*
propogate(it);
block tmp = init(it->l,it->r);
(*it) = tmp;
*/
}
}
int main()
{
ios_base::sync_with_stdio(0); cin.tie(0);
/*
freopen("diskraid.txt","r",stdin);
freopen("diskraidans.txt","w",stdout);
*/
int n, w, q;
cin>>n>>w>>q;
for(int i=0;i<w;i++)
{
for(int j=0;j<n;j++)
{
//read the i-th element of j-th register
cin>>B[i][j];
}
}
recalc(w);
for(int i=0;i<q;i++)
{
char c; cin>>c;
if(c=='Q')
{
int l,r,t;
cin>>l>>r>>t;
unsigned int ans = query(l,r,t);
assert(ans>=0);
//cout<<"Case #"<<i<<" : ";
cout<<ans<<'\n';
}
else if(c=='C')
{
int l,r,t1,t2;
cin>>l>>r>>t1>>t2; //copy t1 into t2
copy(l,r,t1,t2);
}
else if(c=='M')
{
int l,r,t; unsigned int p1,p2;
cin>>l>>r>>t>>p1>>p2; //*p1 + p2 for all [l, r] in t
modify(l,r,t,p1,p2);
}
else if(c=='A')
{
int l,r,t1,t2;
cin>>l>>r>>t1>>t2; //t1*p into t2
unsigned int p;
cin>>p;
advmodify(l,r,t1,t2,p);
}
else
{
int l,r,t1,t2;
cin>>l>>r>>t1>>t2; //swap t1 and t2
swap(l,r,t1,t2);
}
if(int(vec.size())>=BL) recalc(w);
}
}
I2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CiNpbmNsdWRlIDxleHQvcGJfZHMvYXNzb2NfY29udGFpbmVyLmhwcD4KI2luY2x1ZGUgPGV4dC9wYl9kcy90cmVlX3BvbGljeS5ocHA+CiAKdXNpbmcgbmFtZXNwYWNlIHN0ZDsKdXNpbmcgbmFtZXNwYWNlIF9fZ251X3BiZHM7CiAKI2RlZmluZSBmaSBmaXJzdAojZGVmaW5lIHNlIHNlY29uZAojZGVmaW5lIG1wIG1ha2VfcGFpcgojZGVmaW5lIHBiIHB1c2hfYmFjawojZGVmaW5lIGZibyBmaW5kX2J5X29yZGVyCiNkZWZpbmUgb29rIG9yZGVyX29mX2tleQogCnR5cGVkZWYgbG9uZyBsb25nIGxsOwp0eXBlZGVmIHBhaXI8aW50LGludD4gaWk7CnR5cGVkZWYgdmVjdG9yPGludD4gdmk7CnR5cGVkZWYgbG9uZyBkb3VibGUgbGQ7IAp0eXBlZGVmIHRyZWU8aW50LCBudWxsX3R5cGUsIGxlc3M8aW50PiwgcmJfdHJlZV90YWcsIHRyZWVfb3JkZXJfc3RhdGlzdGljc19ub2RlX3VwZGF0ZT4gcGJkczsKdHlwZWRlZiBzZXQ8aW50Pjo6aXRlcmF0b3Igc2l0Owp0eXBlZGVmIG1hcDxpbnQsaW50Pjo6aXRlcmF0b3IgbWl0Owp0eXBlZGVmIHZlY3RvcjxpbnQ+OjppdGVyYXRvciB2aXQ7Cgpjb25zdCBpbnQgQyA9IDM7CmNvbnN0IGludCBCTCA9IDgwMDsKCnVuc2lnbmVkIGludCBCWzEwMDAwMV1bM107CgpzdHJ1Y3QgY2hhbmdlCnsKCXVuc2lnbmVkIGludCBhZGQsbXVsdDsKfTsKCnN0cnVjdCBibG9jawp7CglpbnQgbCxyOwoJY2hhbmdlIG1vZFszXVszXTsKCXVuc2lnbmVkIGludCBzdW1bM107Cn07CgpibG9jayBpbml0KGludCBsLCBpbnQgcikKewoJYmxvY2sgdG1wOwoJbWVtc2V0KHRtcC5zdW0sMCxzaXplb2YodG1wLnN1bSkpOwoJLy8vLy8vLy9jZXJyPDwiU1VNIDogIjw8dG1wLnN1bVswXTw8J1xuJzsKCWZvcihpbnQgaj0wO2o8MztqKyspCgl7CgkJZm9yKGludCBpPWw7aTw9cjtpKyspCgkJewoJCQl0bXAuc3VtW2pdKz1CW2ldW2pdOwoJCQkvLy8vLy9jZXJyPDxpPDwnICc8PGo8PCcgJzw8QltpXVtqXTw8JyAnPDx0bXAuc3VtW2pdPDwnICc8PGw8PCcgJzw8cjw8J1xuJzsKCQl9CgkJLy8vLy8vY2Vycjw8bDw8JyAnPDxyPDwnICc8PHRtcC5zdW1bal08PCdcbic7Cgl9Cglmb3IoaW50IGk9MDtpPDM7aSsrKQoJewoJCWZvcihpbnQgaj0wO2o8MztqKyspCgkJewoJCQl0bXAubW9kW2ldW2pdLmFkZD0wOwoJCQlpZihpPT1qKSB0bXAubW9kW2ldW2pdLm11bHQ9MTsKCQkJZWxzZSB0bXAubW9kW2ldW2pdLm11bHQ9MDsKCQl9Cgl9Cgl0bXAubD1sOyB0bXAucj1yOwoJcmV0dXJuIHRtcDsKfQoKCmxpc3Q8YmxvY2s+IHZlYzsgLy9saW5rZWQgbGlzdCBvZiBibG9ja3MKdHlwZWRlZiBsaXN0PGJsb2NrPjo6aXRlcmF0b3IgbGl0OwoKdW5zaWduZWQgaW50IHF1ZXJ5YmxvY2sobGl0IGEsIGludCBpZHgpCnsKCXJldHVybiBhLT5zdW1baWR4XTsKfQoKdm9pZCBwcm9wb2dhdGUobGl0IGl0KSAvL3VwZGF0ZSBhIGZvciB0aGUgcGFydCBpdAp7CglpbnQgbCA9IGl0LT5sOyBpbnQgciA9IGl0LT5yOwoJZm9yKGludCBpID0gbDsgaSA8PSByOyBpKyspCgl7CgkJdW5zaWduZWQgaW50IHNbM107CgkJZm9yKGludCBqID0gMDsgaiA8IDM7IGorKykKCQl7CgkJCXNbal09MDsKCQkJZm9yKGludCBrID0gMDsgayA8IDM7IGsrKykKCQkJewoJCQkJc1tqXSArPSBCW2ldW2tdKml0LT5tb2Rbal1ba10ubXVsdDsKCQkJCXNbal0gKz0gaXQtPm1vZFtqXVtrXS5hZGQ7CgkJCQkvLy8vY2Vycjw8aXQtPm1vZFtqXVtrXS5tdWx0PDwnICc8PGl0LT5tb2Rbal1ba10uYWRkPDwiIHwgIjsKCQkJfQoJCQkvLy8vY2Vycjw8c1tqXTw8JyAnOwoJCQkvLy8vY2Vycjw8J1xuJzsKCQl9CgkJLy8vL2NlcnI8PCdcbic7CgkJZm9yKGludCBqPTA7ajwzO2orKykgCgkJewoJCQlCW2ldW2pdPXNbal07CgkJfQoJfQkKfQoKdm9pZCByZWNhbGMoaW50IG4pIC8vcmVjYWxjdWxhdGVzIHRoZSB3aG9sZSB0aGluZy4gY2FsbCByZWNhbGModykKewoJZm9yKGxpdCBpdCA9IHZlYy5iZWdpbigpOyBpdCAhPSB2ZWMuZW5kKCk7IGl0KyspCgl7CgkJcHJvcG9nYXRlKGl0KTsKCX0JCgl2ZWMuY2xlYXIoKTsKCWZvcihpbnQgaSA9IDA7IGkgPCBuOyBpKz1CTCkKCXsKCQlpbnQgbCA9IGk7IGludCByID0gbWluKG4tMSxpK0JMLTEpOwoJCXZlYy5wYihpbml0KGwscikpOwoJCS8vLy8vLy8vY2Vycjw8bDw8JyAnPDxyPDwnXG4nOwoJfQp9CiAKbGl0IHNwbGl0KGxpdCBpdCwgaW50IG1pZCkgLy9zcGxpdCBpbnRvIFtsLCBtaWRdIGFuZCBbbWlkKzEsIHJdLiByZXR1cm5zIHRoZSBsYXN0IHBvc2l0aW9uCnsKCWludCBsID0gaXQtPmw7CglpbnQgciA9IGl0LT5yOwoJcHJvcG9nYXRlKGl0KTsKCWJsb2NrIGEgPSBpbml0KGwsbWlkKTsKCWJsb2NrIGIgPSBpbml0KG1pZCsxLHIpOwoJLy8vLy8vY2Vycjw8IlNVTSA6ICI8PGIuc3VtWzBdPDwnXG4nOwoJbGl0IGl0MiA9IHZlYy5pbnNlcnQoaXQsYSk7CglpdDIrKzsKCWxpdCBpdDMgPSB2ZWMuZXJhc2UoaXQyKTsKCXJldHVybiB2ZWMuaW5zZXJ0KGl0MyxiKTsKfQoKdW5zaWduZWQgaW50IHF1ZXJ5KGludCBsLCBpbnQgciwgaW50IGlkeCkKewoJdW5zaWduZWQgaW50IHJlcyA9IDA7Cglmb3IobGl0IGl0ID0gdmVjLmJlZ2luKCk7IGl0ICE9IHZlYy5lbmQoKTsgaXQrKykKCXsKCQlpbnQgTCA9IGl0LT5sOyBpbnQgUiA9IGl0LT5yOwoJCWlmKEw+UikgY29udGludWU7CgkJaWYoUjxsfHxMPnIpIGNvbnRpbnVlOwoJCQoJCWlmKGw8PUwmJlI8PXIpCgkJewoJCQlyZXMrPXF1ZXJ5YmxvY2soaXQsaWR4KTsKCQl9CgkJZWxzZSBpZihMPD1sJiZyPD1SKSAvL0wgbCByIFIKCQl7CgkJCS8vLy8vL2NlcnI8PCJIRVJFIElUIDogIjw8aXQtPmw8PCcgJzw8aXQtPnI8PCcgJzw8aXQtPnN1bVtpZHhdPDwnICc8PEJbMF1bMF08PCcgJzw8aXQtPm1vZFswXVswXS5tdWx0PDwnXG4nOwoJCQlsaXQgdG1wID0gc3BsaXQoaXQsbC0xKTsKCQkJLy8vLy8vY2Vycjw8IkhFUkUgMiA6ICI8PHRtcC0+bDw8JyAnPDx0bXAtPnI8PCcgJzw8dG1wLT5zdW1baWR4XTw8JyAnPDxCWzBdWzBdPDwnXG4nOwoJCQlsaXQgdG1wMiA9IHNwbGl0KHRtcCxyKTsKCQkJdG1wMi0tOwoJCQkvLy8vLy9jZXJyPDwiSEVSRSA6ICI8PHRtcDItPmw8PCcgJzw8dG1wMi0+cjw8JyAnPDx0bXAyLT5zdW1baWR4XTw8J1xuJzsKCQkJaXQ9dG1wMjsKCQkJcmVzKz1xdWVyeWJsb2NrKGl0LGlkeCk7CgkJfQoJCWVsc2UgaWYoTDxsKSAvL0wgbCBSIHIKCQl7CgkJCWxpdCB0bXAgPSBzcGxpdChpdCxsLTEpOwoJCQlpdD10bXA7CgkJCSAvL2NlcnI8PCJMIFIgOiAiPDxpdC0+bDw8JyAnPDxpdC0+cjw8JyAnPDxyZXM8PCcgJzw8cXVlcnlibG9jayhpdCxpZHgpPDwnXG4nOwoJCQlyZXMrPXF1ZXJ5YmxvY2soaXQsaWR4KTsKCQl9CgkJZWxzZSBpZihSPnIpIC8vbCBMIHIgUgoJCXsKCQkJbGl0IHRtcCA9IHNwbGl0KGl0LHIpOwoJCQl0bXAtLTsKCQkJaXQ9dG1wOwoJCQkvL2NlcnI8PCJMIFIgOiAiPDxpdC0+bDw8JyAnPDxpdC0+cjw8JyAnPDxyZXM8PCcgJzw8cXVlcnlibG9jayhpdCxpZHgpPDwnXG4nOwoJCQlyZXMrPXF1ZXJ5YmxvY2soaXQsaWR4KTsKCQl9CgkJZWxzZSBhc3NlcnQoMCk7Cgl9CglyZXR1cm4gcmVzOwp9Cgp2b2lkIGNvcHkoaW50IGwsIGludCByLCBpbnQgdDEsIGludCB0MikKewoJZm9yKGxpdCBpdCA9IHZlYy5iZWdpbigpOyBpdCAhPSB2ZWMuZW5kKCk7IGl0KyspCgl7CgkJaW50IEwgPSBpdC0+bDsgaW50IFIgPSBpdC0+cjsKCQlpZihMPlIpIGNvbnRpbnVlOwoJCWlmKFI8bHx8TD5yKSBjb250aW51ZTsKCQlpZihsPD1MJiZSPD1yKQoJCXsKCQkJZm9yKGludCBqPTA7ajwzO2orKykKCQkJewoJCQkJaXQtPm1vZFt0Ml1bal09aXQtPm1vZFt0MV1bal07CgkJCX0KCQkJaXQtPnN1bVt0Ml09aXQtPnN1bVt0MV07CgkJfQoJCWVsc2UgaWYoTDw9bCYmcjw9UikgLy9MIGwgciBSCgkJewoJCQlsaXQgdG1wID0gc3BsaXQoaXQsbC0xKTsKCQkJbGl0IHRtcDIgPSBzcGxpdCh0bXAscik7CgkJCXRtcDItLTsKCQkJaXQ9dG1wMjsKCQkJZm9yKGludCBqPTA7ajwzO2orKykKCQkJewoJCQkJaXQtPm1vZFt0Ml1bal09aXQtPm1vZFt0MV1bal07CgkJCX0KCQkJaXQtPnN1bVt0Ml09aXQtPnN1bVt0MV07CgkJfQoJCWVsc2UgaWYoTDxsKSAvL0wgbCBSIHIKCQl7CgkJCWxpdCB0bXAgPSBzcGxpdChpdCxsLTEpOwoJCQlpdD10bXA7CgkJCWZvcihpbnQgaj0wO2o8MztqKyspCgkJCXsKCQkJCWl0LT5tb2RbdDJdW2pdPWl0LT5tb2RbdDFdW2pdOwoJCQl9CgkJCWl0LT5zdW1bdDJdPWl0LT5zdW1bdDFdOwoJCX0KCQllbHNlIGlmKFI+cikgLy9sIEwgciBSCgkJewoJCQlsaXQgdG1wID0gc3BsaXQoaXQscik7CgkJCXRtcC0tOwoJCQlpdD10bXA7CgkJCWZvcihpbnQgaj0wO2o8MztqKyspCgkJCXsKCQkJCWl0LT5tb2RbdDJdW2pdPWl0LT5tb2RbdDFdW2pdOwoJCQl9CgkJCWl0LT5zdW1bdDJdPWl0LT5zdW1bdDFdOwoJCX0KCQllbHNlIGFzc2VydCgwKTsKCX0KfQoKdm9pZCBzd2FwKGludCBsLCBpbnQgciwgaW50IHQxLCBpbnQgdDIpCnsKCWZvcihsaXQgaXQgPSB2ZWMuYmVnaW4oKTsgaXQgIT0gdmVjLmVuZCgpOyBpdCsrKQoJewoJCWludCBMID0gaXQtPmw7IGludCBSID0gaXQtPnI7CgkJaWYoTD5SKSBjb250aW51ZTsKCQlpZihSPGx8fEw+cikgY29udGludWU7CgkJaWYobDw9TCYmUjw9cikKCQl7CgkJCWZvcihpbnQgaj0wO2o8MztqKyspCgkJCXsKCQkJCXN3YXAoaXQtPm1vZFt0Ml1bal0saXQtPm1vZFt0MV1bal0pOwoJCQl9CgkJCXN3YXAoaXQtPnN1bVt0Ml0saXQtPnN1bVt0MV0pOwoJCX0KCQllbHNlIGlmKEw8PWwmJnI8PVIpIC8vTCBsIHIgUgoJCXsKCQkJbGl0IHRtcCA9IHNwbGl0KGl0LGwtMSk7CgkJCWxpdCB0bXAyID0gc3BsaXQodG1wLHIpOwoJCQl0bXAyLS07CgkJCWl0PXRtcDI7CgkJCWZvcihpbnQgaj0wO2o8MztqKyspCgkJCXsKCQkJCXN3YXAoaXQtPm1vZFt0Ml1bal0saXQtPm1vZFt0MV1bal0pOwoJCQl9CgkJCXN3YXAoaXQtPnN1bVt0Ml0saXQtPnN1bVt0MV0pOwoJCX0KCQllbHNlIGlmKEw8bCkgLy9MIGwgUiByCgkJewoJCQlsaXQgdG1wID0gc3BsaXQoaXQsbC0xKTsKCQkJaXQ9dG1wOwoJCQlmb3IoaW50IGo9MDtqPDM7aisrKQoJCQl7CgkJCQlzd2FwKGl0LT5tb2RbdDJdW2pdLGl0LT5tb2RbdDFdW2pdKTsKCQkJfQoJCQlzd2FwKGl0LT5zdW1bdDJdLGl0LT5zdW1bdDFdKTsKCQl9CgkJZWxzZSBpZihSPnIpIC8vbCBMIHIgUgoJCXsKCQkJbGl0IHRtcCA9IHNwbGl0KGl0LHIpOwoJCQl0bXAtLTsKCQkJaXQ9dG1wOwoJCQlmb3IoaW50IGo9MDtqPDM7aisrKQoJCQl7CgkJCQlzd2FwKGl0LT5tb2RbdDJdW2pdLGl0LT5tb2RbdDFdW2pdKTsKCQkJfQoJCQlzd2FwKGl0LT5zdW1bdDJdLGl0LT5zdW1bdDFdKTsKCQl9CgkJZWxzZSBhc3NlcnQoMCk7Cgl9Cn0KCnZvaWQgbW9kaWZ5KGludCBsLCBpbnQgciwgaW50IHQsIHVuc2lnbmVkIGludCBwMSwgdW5zaWduZWQgaW50IHAyKQp7Cglmb3IobGl0IGl0ID0gdmVjLmJlZ2luKCk7IGl0ICE9IHZlYy5lbmQoKTsgaXQrKykKCXsKCQlpbnQgTCA9IGl0LT5sOyBpbnQgUiA9IGl0LT5yOwoJCWlmKEw+UikgY29udGludWU7CgkJaWYoUjxsfHxMPnIpIGNvbnRpbnVlOwoJCWlmKGw8PUwmJlI8PXIpCgkJewoJCQlmb3IoaW50IGo9MDtqPDM7aisrKQoJCQl7CgkJCQkvL2l0LT5tb2RbdDJdW2pdPWl0LT5tb2RbdDFdW2pdOwoJCQkJdW5zaWduZWQgaW50IGEgPSBpdC0+bW9kW3RdW2pdLm11bHQ7CgkJCQl1bnNpZ25lZCBpbnQgYiA9IGl0LT5tb2RbdF1bal0uYWRkOwoJCQkJaXQtPm1vZFt0XVtqXS5tdWx0PWEqcDE7CgkJCQlpdC0+bW9kW3RdW2pdLmFkZD1iKnAxOwoJCQl9CgkJCWl0LT5tb2RbdF1bMF0uYWRkKz1wMjsKCQkJaXQtPnN1bVt0XSo9cDE7CgkJCWl0LT5zdW1bdF0rPShSLUwrMSkqcDI7CgkJfQoJCWVsc2UgaWYoTDw9bCYmcjw9UikgLy9MIGwgciBSCgkJewoJCQlsaXQgdG1wID0gc3BsaXQoaXQsbC0xKTsKCQkJbGl0IHRtcDIgPSBzcGxpdCh0bXAscik7CgkJCXRtcDItLTsKCQkJaXQ9dG1wMjsKCQkJZm9yKGludCBqPTA7ajwzO2orKykKCQkJewoJCQkJLy9pdC0+bW9kW3QyXVtqXT1pdC0+bW9kW3QxXVtqXTsKCQkJCXVuc2lnbmVkIGludCBhID0gaXQtPm1vZFt0XVtqXS5tdWx0OwoJCQkJdW5zaWduZWQgaW50IGIgPSBpdC0+bW9kW3RdW2pdLmFkZDsKCQkJCWl0LT5tb2RbdF1bal0ubXVsdD1hKnAxOwoJCQkJaXQtPm1vZFt0XVtqXS5hZGQ9YipwMTsKCQkJfQoJCQlpdC0+bW9kW3RdWzBdLmFkZCs9cDI7CgkJCWl0LT5zdW1bdF0qPXAxOwoJCQlpdC0+c3VtW3RdKz0oaXQtPnItaXQtPmwrMSkqcDI7CgkJfQoJCWVsc2UgaWYoTDxsKSAvL0wgbCBSIHIKCQl7CgkJCWxpdCB0bXAgPSBzcGxpdChpdCxsLTEpOwoJCQlpdD10bXA7CgkJCWZvcihpbnQgaj0wO2o8MztqKyspCgkJCXsKCQkJCS8vaXQtPm1vZFt0Ml1bal09aXQtPm1vZFt0MV1bal07CgkJCQl1bnNpZ25lZCBpbnQgYSA9IGl0LT5tb2RbdF1bal0ubXVsdDsKCQkJCXVuc2lnbmVkIGludCBiID0gaXQtPm1vZFt0XVtqXS5hZGQ7CgkJCQlpdC0+bW9kW3RdW2pdLm11bHQ9YSpwMTsKCQkJCWl0LT5tb2RbdF1bal0uYWRkPWIqcDE7CgkJCX0KCQkJaXQtPm1vZFt0XVswXS5hZGQrPXAyOwoJCQlpdC0+c3VtW3RdKj1wMTsKCQkJaXQtPnN1bVt0XSs9KGl0LT5yLWl0LT5sKzEpKnAyOwoJCQkgLy9jZXJyPDwiU1VNIDogIjw8aXQtPmw8PCcgJzw8aXQtPnI8PCcgJzw8aXQtPnN1bVt0XTw8J1xuJzsKCQl9CgkJZWxzZSBpZihSPnIpIC8vbCBMIHIgUgoJCXsKCQkJbGl0IHRtcCA9IHNwbGl0KGl0LHIpOwoJCQl0bXAtLTsKCQkJaXQ9dG1wOwoJCQlmb3IoaW50IGo9MDtqPDM7aisrKQoJCQl7CgkJCQkvL2l0LT5tb2RbdDJdW2pdPWl0LT5tb2RbdDFdW2pdOwoJCQkJdW5zaWduZWQgaW50IGEgPSBpdC0+bW9kW3RdW2pdLm11bHQ7CgkJCQl1bnNpZ25lZCBpbnQgYiA9IGl0LT5tb2RbdF1bal0uYWRkOwoJCQkJaXQtPm1vZFt0XVtqXS5tdWx0PWEqcDE7CgkJCQlpdC0+bW9kW3RdW2pdLmFkZD1iKnAxOwoJCQl9CgkJCWl0LT5tb2RbdF1bMF0uYWRkKz1wMjsKCQkJaXQtPnN1bVt0XSo9cDE7CgkJCWl0LT5zdW1bdF0rPShpdC0+ci1pdC0+bCsxKSpwMjsKCQkJIC8vY2Vycjw8IlNVTSA6ICI8PGl0LT5sPDwnICc8PGl0LT5yPDwnICc8PGl0LT5zdW1bdF08PCdcbic7CgkJfQoJCWVsc2UgYXNzZXJ0KDApOwoJCS8qCgkJcHJvcG9nYXRlKGl0KTsKCQlibG9jayB0bXAgPSBpbml0KGl0LT5sLGl0LT5yKTsKCQkoKml0KSA9IHRtcDsKCQkqLwoJfQp9Cgp2b2lkIGFkdm1vZGlmeShpbnQgbCwgaW50IHIsIGludCB0MSwgaW50IHQyLCB1bnNpZ25lZCBpbnQgcCkKewoJZm9yKGxpdCBpdCA9IHZlYy5iZWdpbigpOyBpdCAhPSB2ZWMuZW5kKCk7IGl0KyspCgl7CgkJaW50IEwgPSBpdC0+bDsgaW50IFIgPSBpdC0+cjsKCQlpZihMPlIpIGNvbnRpbnVlOwoJCWlmKFI8bHx8TD5yKSBjb250aW51ZTsKCQlpZihsPD1MJiZSPD1yKQoJCXsKCQkJaXQtPnN1bVt0Ml0rPXAqaXQtPnN1bVt0MV07CgkJCWZvcihpbnQgaj0wO2o8MztqKyspCgkJCXsKCQkJCS8vaXQtPm1vZFt0Ml1bal09aXQtPm1vZFt0MV1bal07CgkJCQlpdC0+bW9kW3QyXVtqXS5tdWx0ICs9IGl0LT5tb2RbdDFdW2pdLm11bHQqcDsKCQkJCWl0LT5tb2RbdDJdW2pdLmFkZCArPSBpdC0+bW9kW3QxXVtqXS5hZGQqcDsKCQkJfQoJCX0KCQllbHNlIGlmKEw8PWwmJnI8PVIpIC8vTCBsIHIgUgoJCXsKCQkJbGl0IHRtcCA9IHNwbGl0KGl0LGwtMSk7CgkJCWxpdCB0bXAyID0gc3BsaXQodG1wLHIpOwoJCQl0bXAyLS07CgkJCWl0PXRtcDI7CgkJCWl0LT5zdW1bdDJdKz1wKml0LT5zdW1bdDFdOwoJCQlmb3IoaW50IGo9MDtqPDM7aisrKQoJCQl7CgkJCQkvL2l0LT5tb2RbdDJdW2pdPWl0LT5tb2RbdDFdW2pdOwoJCQkJaXQtPm1vZFt0Ml1bal0ubXVsdCArPSBpdC0+bW9kW3QxXVtqXS5tdWx0KnA7CgkJCQlpdC0+bW9kW3QyXVtqXS5hZGQgKz0gaXQtPm1vZFt0MV1bal0uYWRkKnA7CgkJCX0KCQl9CgkJZWxzZSBpZihMPGwpIC8vTCBsIFIgcgoJCXsKCQkJbGl0IHRtcCA9IHNwbGl0KGl0LGwtMSk7CgkJCWl0PXRtcDsKCQkJaXQtPnN1bVt0Ml0rPXAqaXQtPnN1bVt0MV07CgkJCWZvcihpbnQgaj0wO2o8MztqKyspCgkJCXsKCQkJCS8vaXQtPm1vZFt0Ml1bal09aXQtPm1vZFt0MV1bal07CgkJCQlpdC0+bW9kW3QyXVtqXS5tdWx0ICs9IGl0LT5tb2RbdDFdW2pdLm11bHQqcDsKCQkJCWl0LT5tb2RbdDJdW2pdLmFkZCArPSBpdC0+bW9kW3QxXVtqXS5hZGQqcDsKCQkJfQoJCX0KCQllbHNlIGlmKFI+cikgLy9sIEwgciBSCgkJewoJCQlsaXQgdG1wID0gc3BsaXQoaXQscik7CgkJCXRtcC0tOwoJCQlpdD10bXA7CgkJCWl0LT5zdW1bdDJdKz1wKml0LT5zdW1bdDFdOwoJCQlmb3IoaW50IGo9MDtqPDM7aisrKQoJCQl7CgkJCQkvL2l0LT5tb2RbdDJdW2pdPWl0LT5tb2RbdDFdW2pdOwoJCQkJaXQtPm1vZFt0Ml1bal0ubXVsdCArPSBpdC0+bW9kW3QxXVtqXS5tdWx0KnA7CgkJCQlpdC0+bW9kW3QyXVtqXS5hZGQgKz0gaXQtPm1vZFt0MV1bal0uYWRkKnA7CgkJCX0KCQl9CgkJZWxzZSBhc3NlcnQoMCk7CgkJLyoKCQlwcm9wb2dhdGUoaXQpOwoJCWJsb2NrIHRtcCA9IGluaXQoaXQtPmwsaXQtPnIpOwoJCSgqaXQpID0gdG1wOwoJCSovCgl9Cn0KCmludCBtYWluKCkKewoJaW9zX2Jhc2U6OnN5bmNfd2l0aF9zdGRpbygwKTsgY2luLnRpZSgwKTsKCS8qCglmcmVvcGVuKCJkaXNrcmFpZC50eHQiLCJyIixzdGRpbik7CglmcmVvcGVuKCJkaXNrcmFpZGFucy50eHQiLCJ3IixzdGRvdXQpOwoJKi8KCWludCBuLCB3LCBxOwoJY2luPj5uPj53Pj5xOwoJZm9yKGludCBpPTA7aTx3O2krKykKCXsKCQlmb3IoaW50IGo9MDtqPG47aisrKQoJCXsKCQkJLy9yZWFkIHRoZSBpLXRoIGVsZW1lbnQgb2Ygai10aCByZWdpc3RlcgoJCQljaW4+PkJbaV1bal07CgkJfQoJfQoJcmVjYWxjKHcpOwoJZm9yKGludCBpPTA7aTxxO2krKykKCXsKCQljaGFyIGM7IGNpbj4+YzsKCQlpZihjPT0nUScpCgkJewoJCQlpbnQgbCxyLHQ7CgkJCWNpbj4+bD4+cj4+dDsKCQkJdW5zaWduZWQgaW50IGFucyA9IHF1ZXJ5KGwscix0KTsKCQkJYXNzZXJ0KGFucz49MCk7CgkJCS8vY291dDw8IkNhc2UgIyI8PGk8PCIgOiAiOwoJCQljb3V0PDxhbnM8PCdcbic7CgkJfQoJCWVsc2UgaWYoYz09J0MnKQoJCXsKCQkJaW50IGwscix0MSx0MjsKCQkJY2luPj5sPj5yPj50MT4+dDI7IC8vY29weSB0MSBpbnRvIHQyCgkJCWNvcHkobCxyLHQxLHQyKTsKCQl9CgkJZWxzZSBpZihjPT0nTScpCgkJewoJCQlpbnQgbCxyLHQ7IHVuc2lnbmVkIGludCBwMSxwMjsKCQkJY2luPj5sPj5yPj50Pj5wMT4+cDI7IC8vKnAxICsgcDIgZm9yIGFsbCBbbCwgcl0gaW4gdAoJCQltb2RpZnkobCxyLHQscDEscDIpOwoJCX0KCQllbHNlIGlmKGM9PSdBJykKCQl7CgkJCWludCBsLHIsdDEsdDI7CgkJCWNpbj4+bD4+cj4+dDE+PnQyOyAvL3QxKnAgaW50byB0MgoJCQl1bnNpZ25lZCBpbnQgcDsKCQkJY2luPj5wOwoJCQlhZHZtb2RpZnkobCxyLHQxLHQyLHApOwoJCX0KCQllbHNlCgkJewoJCQlpbnQgbCxyLHQxLHQyOwoJCQljaW4+Pmw+PnI+PnQxPj50MjsgLy9zd2FwIHQxIGFuZCB0MgoJCQlzd2FwKGwscix0MSx0Mik7CgkJfQoJCWlmKGludCh2ZWMuc2l6ZSgpKT49QkwpIHJlY2FsYyh3KTsKCX0KfQo=