我没有数据也没法调啊
#include<bits/stdc++.h>
using namespace std;
#define setAllMax(x) memset(x,0x3f/5,sizeof x)
#define setAllMin(x) memset(x,0xf0,sizeof x)
#define checkMin(x,y) ((x)=(x)<(y)?(x):(y))
#define checkMax(x,y) ((x)=(x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define max(x,y) ((x)>(y)?(x):(y))
inline long long r( ) {
long long x = 0;
short op = 1;
char ch = getchar( );
while( ch != '-' && !( '0' <= ch && ch <= '9' ) ) ch = getchar( );
if( ch == '-' ) op = - 1, ch = getchar( );
while( '0' <= ch && ch <= '9' ) {
x = x * 10 + ch - '0';
ch = getchar( );
}
return x*op;
}
#define inc(i,x,y) for(register int i=x;i<=y;++i)
#define dec(i,x,y) for(register int i=x;i>=y;--i)
#define int long long
class MULTI_SET {
private:
#define PNODE NODE*
struct NODE {
PNODE leftNode;
PNODE rightNode;
int amount;
NODE( ) {
amount = 0;
leftNode = rightNode = NULL;
}
} ;
PNODE root;
int n;
void pushup( PNODE &now ) {
now -> amount = ( now -> leftNode != NULL? now -> leftNode -> amount : 0 )
+ ( now -> rightNode != NULL? now -> rightNode -> amount : 0 );
}
void merge( PNODE &x, PNODE &y, int l, int r ) {
if( y == NULL )
return;
if( x == NULL ) {
x = y;
y = NULL;
return;
}
if( y -> leftNode == NULL && y -> rightNode == NULL ) {
x -> amount += y -> amount;
delete y;
y = NULL;
return;
}
int mid = ( l + r ) >> 1;
merge( x -> leftNode, y -> leftNode, l, mid );
merge( x -> rightNode, y -> rightNode, mid + 1, r );
pushup( x );
delete y;
y = NULL;
}
void merge( PNODE &x, PNODE &y, int l, int r, const int &L, const int &R ) {
if( y == NULL ) return;
if( l > R || r < L )
return;
if( L <= l && r <= R ) {
merge( x, y, l, r );
return;
}
if( x == NULL )
x = new NODE;
int mid = ( l + r ) >> 1;
merge( x -> leftNode, y -> leftNode, l, mid, L, R );
merge( x -> rightNode, y -> rightNode, mid + 1, r, L, R );
pushup( x );
}
void mergeNumber( PNODE &now, int l, int r, const int &amount, const int &value ) {
if( value < l || value > r ) return;
if( now == NULL ) now = new NODE;
if( l == r ) {
now -> amount += amount;
return;
}
int mid = ( l + r ) >> 1;
mergeNumber( now -> leftNode, l, mid, amount, value );
mergeNumber( now -> rightNode, mid + 1, r, amount, value );
pushup( now );
}
int amountInSection( PNODE &now, int l, int r, const int &L, const int &R ) {
if( now == NULL ) return 0;
if( l > R || r < L ) return 0;
if( L <= l && r <= R ) return now -> amount;
int mid = ( l + r ) >> 1;
return amountInSection( now -> leftNode, l, mid, L, R )
+ amountInSection( now -> rightNode, mid + 1, r, L, R );
}
int findByOrder( PNODE &now, int l, int r, int order ) {
if( order > now -> amount ) return - 1;
if( order <= 0 ) return - 1;
if( l == r ) return l;
int mid = ( l + r ) >> 1;
return max( findByOrder( now -> leftNode, l, mid, order ),
findByOrder( now -> rightNode, mid + 1, r, order - now -> leftNode -> amount ) );
}
void print( PNODE now, const int l, const int r ) {
if( now == NULL ) return;
printf( "%lld %lld %lld\n", l, r, now -> amount );
print( now -> leftNode, l, ( l + r ) >> 1 );
print( now -> rightNode, ( ( l + r ) >> 1 ) + 1, r );
}
public:
void free( PNODE &now ) {
if( !now -> leftNode ) free( now -> leftNode );
if( !now -> rightNode ) free( now -> rightNode );
delete now;
now = NULL;
}
void setSize( int N ) {
n = N;
}
void merge( MULTI_SET another ) {
merge( root, another.root, 1, n );
}
void merge( MULTI_SET another, const int L, const int R ) {
merge( root, another.root, 1, n, L, R );
}
void mergeNumber( const int amount, const int value ) {
mergeNumber( root, 1, n, amount, value );
}
int amountInSection( const int L, const int R ) {
return amountInSection( root, 1, n, L, R );
}
int findByOrder( int order ) {
if( order > root -> amount ) return - 1;
return findByOrder( root, 1, n, order );
}
void print( ) {
print( root, 1, n );
}
} ;
MULTI_SET S[ 200005 ];
signed main( ) {
int n, m, k = 1;
n = r( );
m = r( );
inc( i, 1, n )
S[ i ].setSize( n );
inc( i, 1, n ) {
int x = r( );
S[ k ].mergeNumber( x, i );
}
inc( i, 1, m ) {
int opt, a, b, c;
opt = r( );
a = r( );
b = r( );
switch( opt ) {
case 0:
c = r( );
S[ ++ k ].merge( S[ a ], b, c );
break;
case 1:
S[ a ].merge( S[ b ] );
break;
case 2:
c = r( );
S[ a ].mergeNumber( b, c );
break;
case 3:
c = r( );
printf( "%lld\n", S[ a ].amountInSection( b, c ) );
break;
case 4:
printf( "%lld\n", S[ a ].findByOrder( b ) );
break;
}
}
}