最后的财产——模板大全
@
目录
AC自动机
#include<bits/stdc++.h>
using namespace std;
#define ri register int
#define ll long long
#define N 200007
int n,cnt,tot,go[N][26],fail[N],size[N],to[N];
char t[200007],s[2000007];
struct Edge{
int to,next;
}e[N];
int head[N];
inline void add(int from,int to){
e[++tot].to=to;
e[tot].next=head[from];
head[from]=tot;
}
void dfs(int u){
for(ri i=head[u];i!=-1;i=e[i].next){
int v=e[i].to;
dfs(v);
size[u]+=size[v];
}
}
queue<int> q;
int main()
{
scanf("%d",&n);
for(ri i=1;i<=n;++i){
scanf("%s",t);
ri p=0,l=strlen(t);
for(ri j=0;j<l;++j){
int k=t[j]-'a';
if(!go[p][k]) go[p][k]=++cnt;
p=go[p][k];
}
to[i]=p;
}
for(ri i=0;i<26;++i)
if(go[0][i])
q.push(go[0][i]);
while(q.size()){
int p=q.front();
q.pop();
for(ri i=0;i<26;++i){
if(!go[p][i]) go[p][i]=go[fail[p]][i];
else{
q.push(go[p][i]);
fail[go[p][i]]=go[fail[p]][i];
}
}
}
scanf("%s",s);
int len=strlen(s),p=0;
for(ri i=0;i<len;++i){
int j=s[i]-'a';
p=go[p][j];
++size[p];
}
for(ri i=0;i<=cnt;++i) head[i]=-1;
for(ri i=1;i<=cnt;++i)
add(fail[i],i);
dfs(0);
for(ri i=1;i<=n;++i)
printf("%d\n",size[to[i]]);
return 0;
}
BSGS
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int SZ=1991107;
const ll M=998244353;
ll T,n,m,A,B,mod,ans;
template<class T>inline void read(T &res){
static char ch;T flag=1;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') flag=-1; res=ch-48;
while((ch=getchar())>='0'&&ch<='9') res=(res<<1)+(res<<3)+ch-48; res*=flag;
}
struct hash_map{
struct data{
ll u;
int v,nex;
};
data e[SZ<<1];
int h[SZ],cnt;
int hash(ll u){return u%SZ;}
int& operator[](ll u){
int hu=hash(u);
for(int i=h[hu];i;i=e[i].nex)
if(e[i].u==u)
return e[i].v;
return e[++cnt]=(data){u,-1,h[hu]},h[hu]=cnt,e[cnt].v;
}
hash_map(){
cnt=0;
memset(h,0,sizeof(h));
}
void clear(){
cnt=0;
memset(h,0,sizeof(h));
}
}mp;
inline ll fp(ll x,ll k){
ll res=1;
while(k){
if(k&1) res=res*x%mod;
k>>=1;
x=x*x%mod;
}
return res;
}
int main()
{
read(T);
while(T--){
ans=1e13;
mp.clear();
read(A);read(mod);
if(A==0&&A==1){
printf("1\n");
continue;
}
m=ceil(sqrt(mod));
ll tmp1=fp(A,m),tmp2=1;
for(int i=1;i<=m;++i){
tmp2=tmp2*tmp1%mod;
if(mp[tmp2]==-1) mp[tmp2]=i*m;
}
tmp1=A;tmp2=1;
for(int j=0;j<=m;++j){
if(mp[tmp2]!=-1&&mp[tmp2]-j>0) ans=min(ans,(ll)mp[tmp2]-(ll)j);
tmp2=tmp2*tmp1%mod;
}
printf("%lld\n",ans);
}
return 0;
}
KMP
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define ri register int
typedef long long ll;
const int N = 1000007;
char c1[N],c2[N];
int fail[N];
//inline void getfail( char s[] , int len ){
// fail[ 0 ] = fail[ 1 ] = 0;
// for( ri i = 1 ; i < len ; i++ ){
// int t = fail[ i ];
// while( t && s[ i ] != s[ t ] ) t = fail[ t ];
// fail[ i + 1 ] = ( s[ t ] == s[ i ] ? t + 1 : 0 );
// }
//}
//inline void match( char s1[] , char s2[] , int l1 , int l2 ){
// int ans = 0,now = 0;//now指向模式串中下一个准备匹配的字符
// for( ri i = 0 ; i < l2 ; i++ ){
// while( now && s2[ i ] != s1[ now ] ) now = fail[ now ];//失配
// if( s2[ i ] == s1[ now ] ) now++;
// if( now == l1 ) printf( "%d\n" , i - l1 + 2 ),now = fail[ now ];
// }
//}//找在s2中,s1出现的次数,位置
int main()
{
scanf( "%s" , c2 );scanf( "%s" , c1 );
// getfail( c1 , strlen( c1 ) );
// match( c1 , c2 , strlen( c1 ) , strlen( c2 ) );
// for( ri i = 1 ; i <= len ; i++ )
// printf( "%d " , fail[ i ] )
fail[ 0 ] = fail[ 1 ] = 0;int len = strlen( c1 );
for( ri i = 1 ; i < len ; i++ ){
int t = fail[ i ];
while( t && c1[ i ] != c1[ t ] ) t = fail[ t ];
fail[ i + 1 ] = ( c1[ t ] == c1[ i ] ? t + 1 : 0 );
}
register int now = 0,l1 = len,l2 = strlen( c2 );//now指向模式串中下一个准备匹配的字符
for( ri i = 0 ; i < l2 ; i++ ){
while( now && c2[ i ] != c1[ now ] ) now = fail[ now ];//失配
if( c2[ i ] == c1[ now ] ) now++;
if( now == l1 ) printf( "%d\n" , i - l1 + 2 ),now = fail[ now ];
}
for( ri i = 1 ; i <= len ; i++ )
printf( "%d " , fail[ i ] );
return 0;
}
马拉车
#include<bits/stdc++.h>
using namespace std;
#define j (id<<1)-i
const int N=11000007;
char t[N],s[N<<1];
int pal[N<<1];
inline int min(int a,int b){
return a<b?a:b;
}
inline int max(int a ,int b){
return a>b?a:b;
}
int main()
{
scanf("%s",t);
s[0]='+';
int len=strlen(t);
for(int i=1;i<(len<<1);i+=2){
s[i]='#';
s[i+1]=t[i>>1];
}
s[(len<<1)+1]='#';
s[(len<<1)+2]='-';
s[(len<<1)+3]='\0';
int mx=0,id=0;
len=(len<<1)+1;
for(int i=1;i<=len;i++){
if(mx>=i) pal[i]=min(mx-i+1,pal[j]);
else pal[i]=1;
while(s[i+pal[i]]==s[i-pal[i]]) pal[i]++;//暴力
if(i+pal[i]-1>mx){
mx=i+pal[i]-1;
id=i;
}
}
int maxn=0;
for(int i=1;i<=len;i++) maxn=max(maxn,pal[i]);
printf("%d\n",maxn-1);
return 0;
}
最长公共子序列
#include<cstdio>
#include<cstring>
using namespace std;
#define ri register int
const int N = 100005;
int n,len,a[N],ord[N],b[N],f[N];
template<class T>inline void read(T &res){static char ch;T flag = 1;
while( ( ch = getchar() ) < '0' || ch > '9' ) if( ch == '-' ) flag = -1;res = ch - 48;
while( ( ch = getchar() ) >= '0' && ch <= '9' ) res = res * 10 + ch - 48;res *= flag;
}
int main()
{
read( n );
for( ri i = 1 ; i <= n ; i++ ) {read( a[ i ] );ord[ a[ i ] ] = i;}
for( ri i = 1 ; i <= n ; i++ ){read( b[ i ] );b[ i ] = ord[ b[ i ] ];}
memset( f , 0 , sizeof( f ) );f[ 1 ] = b[ 1 ];len = 1;
for( ri i = 2 ; i <= n ; i++ ){
if( b[ i ] > f[ len ] ){f[ ++len ] = b[ i ];continue;}
int l = 1,r = len,mid;
while( l <= r ){
mid = ( l + r ) >> 1;
if( f[ mid ] > b[ i ] ) r = mid - 1;
else l = mid + 1;
}f[ l ] = b[ i ];
}printf( "%d" , len );
return 0;
}
最小生成树
#include<bits/stdc++.h>
using namespace std;
struct Edge{
int a,b,dis;
}e[500000];//无向边,存边
int father[100000];
int p,edge,tot=1,ans=0;
template<class T>inline void read(T &res){
static char ch;T flag=1;
while((ch=getchar())<'0'||ch>'9')if(ch=='-')flag=-1;res=ch-48;
while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-48;res*=flag;
}
int find( int x )
{
if( father[ x ] != x )
father[ x ]=find( father[ x ] );
return father[ x ];
}
void unionn( int x , int y )
{
father[ y ]=father[ x ];
}
bool cmp( Edge x , Edge y )
{
return x.dis<y.dis;
}
void kruskal()
{
sort( e + 1 , e + edge + 1 , cmp );
for( int i = 1 ; i <= edge && tot <= p ; i ++ )
{
int r1=find( e[ i ].a ),r2=find( e[ i ].b );
if( r1 == r2 )//判断两点是否已经在最小生成树中
continue;
unionn( r1 , r2 );
tot++;
ans+=e[ i ].dis;
}
cout<<ans;
}
int main()
{
cin>>p>>edge;
for( int i = 1 ; i <= p ; i ++ )
father[ i ]=i;//并查集初始化,自己叫自己爸爸
for( int i = 1 ; i <= edge ; i ++ )
read( e[ i ].a ),read( e[ i ].b ),read( e[ i ].dis );
kruskal();
return 0;
}
LCA
#include<cstdio>
#include<algorithm>
using namespace std;
#define oo 0x3f3f3f3f
#define ri register int
const int N = 500007;
typedef long long ll;
int n,m,s,tot,head[N],son[N],fa[N],top[N],size[N],deep[N];
struct Edge{
int to,next;
}e[N<<1];
inline void add( int x , int y ){
e[ ++tot ].to = y;
e[ tot ].next = head[ x ];
head[ x ] = tot;
}
template<class T>inline void read(T &res){
static char ch;T flag = 1;
while( ( ch = getchar() ) < '0' || ch > '9' ) if( ch == '-' ) flag = -1;
res = ch - 48;
while( ( ch = getchar() ) >= '0' && ch <= '9' ) res = res * 10 + ch - 48;
res *= flag;
}
void dfs1( int u ){
size[ u ] = 1;
for( ri i = head[ u ] ; i ; i = e[ i ].next ){
int v = e[ i ].to;
if( fa[ u ] == v ) continue;
fa[ v ] = u;deep[ v ] = deep[ u ] + 1;
dfs1( v );
size[ u ] += size[ v ];
if( !son[ u ] || size[ son[ u ] ] < size[ v ] )
son[ u ] = v;
}
}
void dfs2( int u , int tp ){
top[ u ] = tp;
if( son[ u ] ) dfs2( son[ u ] , tp );
for( ri i = head[ u ] ; i ; i = e[ i ].next ){
int v = e[ i ].to;
if( v == son[ u ] || v == fa[ u ] ) continue;
dfs2( v , v );
}
}
int main()
{
read( n );read( m );read( s );
for( ri i = 1 ; i <= n - 1 ; i++ ){
int x,y;
read( x );read( y );
add( x , y );
add( y , x );
}tot = 0;deep[ s ] = 1;
dfs1( s );
dfs2( s , s );
for( ri i = 1 ; i <= m ; i++ ){
int x,y;read( x );read( y );
while( top[ x ] != top[ y ] ){
if( deep[ top[ x ] ] < deep[ top[ y ] ] ) swap( x , y );
x = fa[ top[ x ] ];
}
printf( "%d\n" , deep[ x ] > deep[ y ] ? y : x );
}
return 0;
}
哈希
// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<map>
using namespace std;
#define UL unsigned long long
#define BASE 1000000007
int n,ans = 0;
string s;
map<UL,int> judge;
void hash( string s ){
UL cnt = 0;
for( register int i = 0 ; i <= s.length() - 1 ; i++ )
cnt = ( cnt + s[ i ] ) * BASE ;
if( !judge[ cnt ] ) ans++;
judge[ cnt ]++;
}
int main(){
cin>>n;
for( register int j = 1 ; j <= n ; j++ ){
cin>>s;
hash( s );
}
printf( "%d" , ans );
return 0;
}
值域线段树
#include<bits/stdc++.h>
using namespace std;
#define ri register int
#define mid ((l+r)>>1)
const int N=500007;
int n,num,ndnum,a[N],b[N],ls[N],rs[N],sum[N];
template<class T> inline void read(T &res){
T flag=1;static char ch;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') flag=-1;
res=ch-'0';
while((ch=getchar())>='0'&&ch<='9') res=(res<<1)+(res<<3)+ch-'0';
res*=flag;
}
int build(int l,int r){
int p=++ndnum;
if(l==r) return p;
ls[p]=build(l,mid);
rs[p]=build(mid+1,r);
return p;
}
void insert(int x,int p,int l,int r){
if(l==r){
++sum[p];
return;
}
if(x<=b[mid])
insert(x,ls[p],l,mid);
else
insert(x,rs[p],mid+1,r);
sum[p]=sum[ls[p]]+sum[rs[p]];
}
int find(int rk,int p,int l,int r){
if(l==r)
return l;
if(rk<=sum[ls[p]])
return find(rk,ls[p],l,mid);
return find(rk-sum[ls[p]],rs[p],mid+1,r);
}
int main()
{
read(n);
for(ri i=1;i<=n;++i) read(a[i]),b[i]=a[i];
sort(b+1,b+n+1);
num=unique(b+1,b+n+1)-b-1;
build(1,num);
insert(a[1],1,1,num);
printf("%d\n",a[1]);
for(ri i=2;i<=n;++i){
insert(a[i],1,1,num);
if(i%2==1) printf("%d\n",b[find((i+1)>>1,1,1,num)]);
}
return 0;
}
线性筛素数
#include<bits/stdc++.h>
using namespace std;
int zs[10000010],bc[2000010],tot=0;
void search(int n){
for(int i=2;i<=n;i++){
if(zs[i]==0)
bc[++tot]=i;
for(int j=1;j<=tot&&bc[j]*i<=n;j++){
zs[bc[j]*i]=1;
if(i%bc[j]==0)
break;
}
}
}
int main(){
freopen("group.out","w",stdout);
int n,m,t;
zs[0]=1;
zs[1]=1;
scanf("%d",&n);
search(n);
// scanf("%d",&m);
// for(int i=1;i<=m;i++){
// scanf("%d",&t);
// bc[i]=t;
// }
// for(int i=1;i<=m;i++){
// if(zs[bc[i]]==0) printf("Yes\n");
// else printf("No\n");
// }
for(int i=1;i<=2000000;++i) printf("%d ",bc[i]);
return 0;
}
线性筛逆元
#include<bits/stdc++.h>
using namespace std;
#define ri register int
#define ll long long
long long n,p,inv[3000007];
int main()
{
cin>>n>>p;
inv[1]=1;
for(int i=2;i<=n;++i)
inv[i]=(p-p/i)*inv[p%i]%p;
for(int i=1;i<=n;++i) printf("%lld\n",inv[i]);
return 0;
}
线段树
#include<cstdio>
using namespace std;
#define N 100007
typedef long long ll;
int n,m,tot=0,p;
ll a[N];
struct Node{
ll sum,flag,cflag;
Node *ls,*rs;
Node(){
sum = flag = 0;
cflag = 1;
ls = rs = NULL;
}
inline void pushdown( int l , int r ){
int mid = ( l + r ) >> 1;
ls->sum = ( ls->sum * cflag % p + flag * ( mid - l + 1 ) % p ) % p;
rs->sum = ( rs->sum * cflag % p + flag * ( r - mid ) % p ) % p;
ls->flag = ( ls->flag * cflag + flag ) % p;
rs->flag = ( rs->flag * cflag + flag ) % p;
ls->cflag = cflag * ls->cflag % p;
rs->cflag = cflag * rs->cflag % p;
flag = 0;cflag = 1;
}
inline void update(){
sum = ( ls->sum + rs->sum ) %p;
}
}tree[N<<1],*q = tree,*root;
Node *build( int l , int r ){
Node *nd = ++q;
if( l == r ){
nd->sum = a[ l ] % p;
return nd;
}
int mid = ( l + r )>>1;
nd->ls = build( l , mid );
nd->rs = build( mid + 1 , r );
nd->update();
return nd;
}
ll query( int l , int r , int x , int y , Node *nd ){
if( x <= l && y >= r )
return nd->sum;
if( l > y || r < x )
return 0;
nd->pushdown( l , r );
int mid = ( l + r ) >> 1;
return query( l , mid , x , y , nd->ls ) + query( mid + 1 , r , x , y , nd->rs );
}
void modify( int l , int r , int x , int y , int add , Node *nd )
{
if( x <= l && r <= y ) {
nd->sum = ( nd->sum + ( r - l + 1 ) * add ) % p;
nd->flag = ( nd->flag + add ) %p;
return;
}
int mid = ( l + r ) >> 1;
nd->pushdown( l , r );
if( x <= mid )
modify( l , mid , x , y , add , nd->ls );
if( y > mid )
modify( mid + 1 , r , x , y , add , nd->rs );
nd->update();
}
void cmodify( int l , int r , int x , int y , int c , Node *nd ){
if( x <= l && r <= y ) {
nd->sum = nd->sum * c % p;
nd->flag = nd->flag * c % p;
nd->cflag = nd->cflag * c % p;
return;
}
int mid = ( l + r ) >> 1;
nd->pushdown( l , r );
if( x <= mid )
cmodify( l , mid , x , y , c , nd->ls );
if( y > mid )
cmodify( mid + 1 , r , x , y , c , nd->rs );
nd->update();
}
int main()
{
scanf( "%d %d %d" , &n , &m , &p );
for( register int i = 1 ; i <= n ; i ++ )
scanf( "%lld" , &a[ i ] );
root=build( 1 , n );
for( register int i = 1 ; i <= m ; i ++ ){
int f;
scanf( "%d" , &f );
switch( f ){
case 2:{
int x,y,add;
scanf( "%d %d %d" , &x , &y , &add );
modify( 1 , n , x , y , add , root );
break;
}
case 1:{
int x,y,add;
scanf( "%d %d %d" , &x , &y , &add );
cmodify( 1 , n , x , y , add , root );
break;
}
case 3:{
int x,y;
scanf( "%d %d" , &x , &y );
printf( "%lld\n" , query( 1 , n , x , y , root ) % p );
break;
}
}
}
return 0;
}
舞蹈链
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
#define oo 0x3f3f3f3f
#define N 253510
#define XN 505
#define head 0
typedef long long ll;
int n,m,cnt;
int left[ N ] = {},right[ N ] = {},up[ N ] = {},down[ N ] = {};
int col[ N ] = {},row[ N ] = {};
int ans[ XN ] = {};
int col_cnt[ XN ] = {};
int row_first[ XN ] = {};
template<class T>
inline void read(T &res){
static char ch;T flag = 1;
while( ( ch = getchar() ) < '0' || ch > '9' )
if( ch == '-' ) flag = -1;
res = ch - 48;
while( ( ch = getchar() ) >= '0' && ch <= '9' )
res = res * 10 + ch - 48;
res *= flag;
}
inline void chushihua(){
memset( row_first , -1 , sizeof( row_first ) );
for( int i = 0 ; i <= m ; i++ ){
up[ i ] = down[ i ] = i;
right[ i ] = i + 1;
left[ i ] = i - 1;
}
left[ head ] = m;right[ m ] = head;
cnt = m;
}
inline void charu( int hang , int lie ){
col_cnt[ lie ]++;
row[ ++cnt ] = hang;col[ cnt ] = lie;
up[ cnt ] = lie;
down[ cnt ] = down[ lie ];
up[ down[ lie ] ] = cnt;
down[ lie ] = cnt;
if( row_first[ hang ] == -1 ) row_first[ hang ] = right[ cnt ] = left[ cnt ] = cnt;
else{
right[ cnt ] = row_first[ hang ];
left[ cnt ] = left[ row_first[ hang ] ];
right[ left[ row_first[ hang ] ] ] = cnt;
left[ row_first[ hang ] ] = cnt;
}
}
inline void shanchu( int l ){
right[ left[ l ] ] = right[ l ];left[ right[ l ] ] = left[ l ];
for( int i = down[ l ] ; i != l ; i = down[ i ] )
for( int j = right[ i ] ; j != i ; j = right[ j ] ){
down[ up[ j ] ] = down[ j ];
up[ down[ j ] ] = up[ j ];
col_cnt[ col[ j ] ]--;
}
}
inline void huifu(int l){
for( int i = up[ l ] ; i != l ; i = up[ i ] )
for( int j = left[ i ] ; j != i ; j = left[ j ] ){
down[ up[ j ] ] = up[ down[ j ] ] = j;
col_cnt[ col[ j ] ]++;
}
left[ right[ l ] ] = right[ left[ l ] ] = l;
}
bool Dance( int piece ){
if( right[ head ] == head ){
for( int i = 0; i < piece ; ++i )
printf( "%d\n" , ans[ i ] );
return true;
}
int l = right[ head ];
for( register int i = right[ head ] ; i != head ; i = right[ i ] )
if( col_cnt[ i ] < col_cnt[ l ] ) l = i;
shanchu( l );
for( register int i = down[ l ] ; i != l ; i = down[ i ] ){
ans[ piece ] = row[ i ];
for( register int j = right[ i ] ; j != i ; j = right[ j ] )
shanchu( col[ j ] );
if( Dance( piece + 1 ) ) return true;
for( register int j = left[ i ] ; j != i ; j = left[ j ] )
huifu( col[ j ] );
}
huifu( l );
return false;
}
int main()
{
read( n ),read( m );
chushihua();
for( register int i = 1 ; i <= n ; i++ )
for( register int j = 1 ; j <= m ; j++ ){
int x;read( x );
if( x == 1 ) charu( i , j );
}
if( !Dance( 0 ) ) printf( "No Solution!\n" );
return 0;
}
文艺平衡树
#include<bits/stdc++.h>
using namespace std;
#define ri register int
#define ll long long
#define INF 200000
const int N=200001;
int a[N];
int n,m;
template<class T>inline void read(T &res){
static char ch;T flag=1;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') flag=-1;
res=ch-48;
while((ch=getchar())>='0'&&ch<='9') res=(res<<1)+(res<<3)+ch-48;
res*=flag;
}
class Splay{
public:
int root=0,ndnum=0,son[N][2],fa[N],size[N],cnt[N],val[N];
bool tag[N];
inline void update(int p){
size[p]=size[son[p][0]]+size[son[p][1]]+cnt[p];
}
inline void pushdown(int p){
if(tag[p]){
if(son[p][0]) tag[son[p][0]]^=1;
if(son[p][1]) tag[son[p][1]]^=1;
swap(son[p][0],son[p][1]);
tag[p]^=1;
}
}
inline bool check(int p){
return p==son[fa[p]][1];
}
inline void rotate(int p){
int f=fa[p],ff=fa[f],k=check(p),kk=check(f),nd=son[p][k^1];
son[ff][kk]=p;fa[p]=ff;
son[p][k^1]=f;fa[f]=p;
son[f][k]=nd;fa[nd]=f;
update(f);update(p);
}
inline void splay(int p,int goal){
if(p==goal) return;
while(fa[p]!=goal){
int f=fa[p],ff=fa[f];
if(ff!=goal){
if(check(p)==check(f))
rotate(f);
else rotate(p);
}
rotate(p);
}
if(goal==0) root=p;
}
inline int search(int rk){
int p=root;
while(1){
pushdown(p);
if(son[p][0]&&rk<=size[son[p][0]]) p=son[p][0];
else if(rk>size[son[p][0]]+cnt[p]){
rk-=size[son[p][0]]+cnt[p];
p=son[p][1];
}
else return p;
}
}
inline void insert(int x){
int f=0,cur=root;
while(cur&&x!=val[cur]){
f=cur;
cur=son[cur][x>val[cur]];
}
if(cur) ++cnt[cur];
else{
cur=++ndnum;
fa[cur]=f;
son[cur][0]=son[cur][1]=0;
size[cur]=cnt[cur]=1;
val[cur]=x;
if(f) son[f][x>val[f]]=cur;
}
splay(cur,0);
}
inline void reverse(int l,int r){
l=search(l);r=search(r+2);
splay(l,0);splay(r,l);
tag[son[r][0]]^=1;
}
inline void bianli(int p){
pushdown(p);
if(son[p][0]) bianli(son[p][0]);
if(val[p]<n+2&&val[p]>1)
printf("%d ",val[p]-1);
if(son[p][1]) bianli(son[p][1]);
}
}Tree;
int main()
{
read(n);read(m);
for(ri i=1;i<=n+2;++i) Tree.insert(i);
for(ri i=1;i<=m;++i){
int l,r;
read(l);read(r);
Tree.reverse(l,r);
}
Tree.bianli(Tree.root);
return 0;
}
最大流
//dinic算法
#include<bits/stdc++.h>
using namespace std;
#define oo 0x3f3f3f3f
#define N 150005
#define M 15005
#define ri register int
typedef long long ll;
int timer = 0,n,m,s,t,tot = -1,head[M],dis[M],vis[M],cur[M];
struct Edge{
int to,next,w;
}e[N<<1];
template<class T>
inline void read(T &res){
static char ch;T flag = 1;
while( ( ch = getchar() ) < '0' || ch > '9' )
if( ch == '-' ) flag = -1;
res = ch - 48;
while( ( ch = getchar() ) >= '0' && ch <= '9' )
res = res * 10 + ch - 48;
res *= flag;
}
inline void add( int from , int to , int w ){
e[ ++tot ].to = to;
e[ tot ].w = w;
e[ tot ].next = head[ from ];
head[ from ] = tot;
}
int dfs( int x , int lim ){
if( x == t ) return lim;
int ans = 0;
for( ri i = cur[ x ] ; i != -1 ; i = e[ i ].next ){
cur[ x ] = i;
if( e[ i ].w && dis[ e[ i ].to ] == dis[ x ] + 1 ){
int y = dfs( e[ i ].to , min( e[ i ].w , lim ) );
if( y ){
e[ i ].w -= y;e[ i^1 ].w += y;
ans += y;lim -= y;
if( !lim ) return ans;
}
}
}
return ans;
}
inline bool bfs(){
timer++;
queue<int> q;
dis[ s ] = 0;vis[ s ] = timer;
q.push( s );
while( !q.empty() ){
int x = q.front();q.pop();
for( ri i = head[ x ] ; i != -1 ; i = e[ i ].next ){
int v = e[ i ].to;
if( e[ i ].w == 0 ) continue;
if( vis[ v ] != timer ){
vis[ v ] = timer;
dis[ v ] = dis[ x ] + 1;
q.push( v );
}
}
}
return vis[ t ] == timer;
}//判断是否可以增广
int dinic(){
int ans = 0;
while( bfs() ){
for( ri i = 1 ; i <= n ; i++ ) cur[ i ] = head[ i ];
ans += dfs( s , 2147483647 );
}
return ans;
}
int main()
{
read( n );read( m );read( s );read( t );
for( ri i = 1 ; i <= n ; i++ ) head[ i ] = -1;//初始化
for( ri i = 1 ; i <= m ; i++ ){
int x,y,z;read( x );read( y );read( z );
add( x , y , z );add( y , x , 0 );//建边的同时要建一条虚拟边
}
cout<<dinic();
return 0;
}
缩点
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<stack>
using namespace std;
#define oo 0x3f3f3f3f
#define N 10010
typedef long long ll;
int ans = 0,n,m,tot = 0,cnt= 0,vf[ N ],low[ N ],w[ N ],head[ N ],nhead[ N ],bel[ N ],np[ N ],g[ N ];
bool est[ N ];
stack<int> q;
struct Edge{
int to,next,from;
}e[ N * 10 ],ne[ N * 10 ];
template<class T>
inline void read(T &res){
static char ch;T flag = 1;
while( ( ch = getchar() ) < '0' || ch > '9' )
if( ch == '-' ) flag = -1;
res = ch - 48;
while( ( ch = getchar() ) >= '0' && ch <= '9' )
res = res * 10 + ch - 48;
res *= flag;
}
inline void add( int from , int to ){
e[ ++tot ].to = to;
e[ tot ].next = head[ from ];
e[ tot ].from = from;
head[ from ] = tot;
}
inline void nadd( int from , int to ){
ne[ ++tot ].to = to;
ne[ tot ].next = nhead[ from ];
ne[ tot ].from = from;
nhead[ from ] = tot;
}
void tarjan( int x ){
q.push( x );vf[ x ] = low[ x ] = ++cnt;est[ x ] = true;
for( register int i = head[ x ] ; i ; i = e[ i ].next ){
int v = e[ i ].to;
if( !vf[ v ] ){tarjan( v );low[ x ] = min( low[ x ] , low[ v ] );}//没被访问
else if( est[ v ] ) low[ x ] = min( low[ x ] , vf[ v ] ); //在栈中
}
if( vf[ x ] == low[ x ] ){
int v;tot++;
while( v = q.top() ){
bel[ v ] = tot;np[ tot ] += w[ v ];//缩点
// printf( "%d " , v );
est[ v ] = false;q.pop();
if( v == x ) break;
}
// printf( "\n" );
}//弹栈
}
void search( int x ){
if( g[ x ] ) return;
g[ x ] = np[ x ];
int maxn = 0;
for( int i = nhead[ x ] ; i ; i = ne[ i ].next ){
if( !g[ ne[ i ].to ] ) search( ne[ i ].to );
maxn = max( maxn , g[ ne[ i ].to ] );
}
g[ x ] += maxn;
}//记忆化搜索
int main()
{
read( n );read( m );
for( register int i = 1 ; i <= n ; i++ ) read( w[ i ] );
//读入点权
for( register int i = 1 ; i <= m ; i++ ){
int x,y;read( x );read( y );
add( x , y );
}tot = 0;//建边
for( register int i = 1 ; i <= n ; i++ )
if( !vf[ i ] ) tarjan( i );//tarjan找强连通分量
for( register int i = 1 ; i <= m ; i++ ){//枚举每条边
int x = e[ i ].from,y = e[ i ].to;
if( bel[ x ] == bel[ y ] ) continue;
nadd( bel[ x ] , bel[ y ] );//建新图
}
// for( register int i = 1 ; i <= tot ; i++ )
// printf( "%d " , np[ i ] );
for( register int i = 1 ; i <= tot ; i++ )
if( !g[ i ] ){
search( i );
ans = max( ans , g[ i ] );
}
printf( "%d" , ans );
return 0;
}
树状数组
#include<bits/stdc++.h>
using namespace std;
int a[500005];
int c[500005];
int ans[500005];
int num,x,tot=0;
int lowbit( int x )//求一个数在二进制表示下最低位的1以及它后面的0构成的数值
{
return x & ( - x );//与运算
}
void update( int ord , int s )//修改
{
a[ ord ]+=s;
while( ord <= num )
{
c[ ord ]+=s;
ord+=lowbit( ord );
}
}
int sum( int k )//查询前缀和
{
int anss=0;
while( k )
{
anss+=c[ k ];
k-=lowbit( k );
}
return anss;
}
int main()
{
scanf( "%d%d" , &num , &x );
for( int i = 1 ; i <= num ; i ++ )
{
scanf( "%d" , &a[ i ] );
update( i , a[ i ] );
}
for( int i = 1 ; i <= x ; i ++ )
{
int k;
scanf( "%d" , &k );
if( k == 1 )//修改
{
int ord,s;
scanf( "%d%d" , &ord , &s );
update( ord , s );
continue;
}
//查询
int l,r;
scanf( "%d%d" , &l , &r );
ans[ ++ tot ]=sum( r )-sum( l - 1 );
}
for( int i = 1 ; i <= tot - 1 ; i ++ )
printf( "%d\n" , ans[ i ] );
printf( "%d" , ans[ tot ] );
return 0;
}
树剖
#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
#define N 500005
#define ri register int
int tot=0,n,m,rt,md;
int fa[N],deep[N],head[N],size[N],son[N],id[N],w[N],nw[N],top[N];
struct EDGE{
int to,next;
}e[N];
inline void add(int from,int to){
e[++tot].to=to;
e[tot].next=head[from];
head[from]=tot;
}
template<class T>inline void read(T &res){
static char ch;T flag=1;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') flag=-1; res=ch-48;
while((ch=getchar())>='0'&&ch<='9') res=(res<<1)+(res<<3)+ch-48; res*=flag;
}
struct NODE{
ll sum,flag;
NODE *ls,*rs;
NODE(){
sum=flag=0;
ls=rs=NULL;
}
inline void pushdown(int l,int r){
if(flag){
int midd=(l+r)>>1;
ls->flag+=flag;
rs->flag+=flag;
ls->sum+=flag*(midd-l+1);
rs->sum+=flag*(r-midd);
flag=0;
}
}
inline void update(){
sum=ls->sum+rs->sum;
}
}tree[N*2+5],*p=tree,*root;
NODE *build(int l,int r){
NODE *nd=++p;
if(l==r){
nd->sum=nw[l];
return nd;
}
int mid=(l+r)>>1;
nd->ls=build(l,mid);
nd->rs=build(mid+1,r);
nd->update();
return nd;
}
ll sum(int l,int r,int x,int y,NODE *nd){
if(x<=l&&r<=y) return nd->sum;
nd->pushdown(l,r);
int mid=(l+r)>>1;
ll res=0;
if(x<=mid) res+=sum(l,mid,x,y,nd->ls);
if(y>=mid+1) res+=sum(mid+1,r,x,y,nd->rs);
return res;
}
void modify(int l,int r,int x,int y,ll add,NODE *nd){
if(x<=l&&r<=y){
nd->sum+=(r-l+1)*add;
nd->flag+=add;
return;
}
int mid=(l+r)>>1;
nd->pushdown(l,r);
if(x<=mid) modify(l,mid,x,y,add,nd->ls);
if(y>mid) modify(mid+1,r,x,y,add,nd->rs);
nd->update();
}
void dfs1(int p){
size[p]=1;
deep[p]=deep[fa[p]]+1;
for(int i=head[p];i;i=e[i].next){
int k=e[i].to;
if(k==fa[p]) continue;
fa[k]=p;
dfs1(k);
size[p]+=size[k];
if(size[son[p]]<size[k]||!son[p]) son[p]=k;
}
}//第一次预处理,找到各个点的深度,size,重儿子,爸爸
void dfs2(int p,int tp){//第二次预处理,找出重链,dfs序
id[p]=++tot;//每个点在dfs序里的位置
nw[tot]=w[p];
top[p]=tp;
if(son[p]) dfs2(son[p],tp);//重链
for(int i=head[p];i;i=e[i].next){
int k=e[i].to;
if(k==fa[p]||k==son[p]) continue;
dfs2(k,k);//轻链
}
}
inline void ope1(int x,int y,ll add){
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]]) swap(x,y);//注意是deep[top[x]]!
modify(1,n,id[top[x]],id[x],add,root);
x=fa[top[x]];
}
if(deep[x]>deep[y]) swap(x,y);
modify(1,n,id[x],id[y],add,root);
}
inline ll ope2(int x,int y){
ll res=0;
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]]) swap(x,y);
res+=sum(1,n,id[top[x]],id[x],root);
x=fa[top[x]];
}
if(deep[x]>deep[y]) swap(x,y);
res+=sum(1,n,id[x],id[y],root);
return res;
}
inline void ope3(int x,int add){
modify(1,n,id[x],id[x]+size[x]-1,add,root);
}
inline ll ope4(int x){
return sum(1,n,id[x],id[x]+size[x]-1,root);
}
int main()
{
cin>>n>>m>>rt>>md;
for(ri i=1;i<=n;i++)
read(w[i]);//点权
for(ri i=1;i<=n-1;i++){
int x,y;
read(x),read(y);
add(x,y);
add(y,x);
}
dfs1(rt),tot=0;
dfs2(rt,rt);
root=build(1,n);
for(ri i=1;i<=m;i++){
int f;
read(f);
switch(f){
case 1:{//链修改
int x,y;
ll add;
read(x),read(y),read(add);
ope1(x,y,add);
break;
}
case 2:{//链查询
int x,y;
read(x),read(y);
printf("%lld\n",ope2(x,y)%md);
break;
}
case 3:{//子树修改
int x;
ll add;
read(x),read(add);
ope3(x,add);
break;
}
case 4:{//子树查询
int x;
read(x);
printf("%lld\n",ope4(x)%md);
break;
}
}
}
return 0;
}
三维偏序
#include<bits/stdc++.h>
using namespace std;
#define ri register int
#define ll long long
const int N=300007;
int n,k,tot,sum[N],to[N],Ans[N],tong[N];
class Node{
public:
int a,b,c,t,cnt,ans;
}node[N],po[N],P[N];
template<class T>inline void read(T &res){
static char ch;T flag=1;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') flag=-1;
res=ch-48;
while((ch=getchar())>='0'&&ch<='9') res=(res<<1)+(res<<3)+ch-48;
res*=flag;
}
inline int lowbit(int x){
return x&(-x);
}
inline void update(int sta,int x){
while(sta<=k){
sum[sta]+=x;
sta+=lowbit(sta);
}
}
inline int query(int sta){
int res=0;
while(sta>0){
res+=sum[sta];
sta-=lowbit(sta);
}
return res;
}
inline bool cmp(Node x,Node y){
if(x.a==y.a&&x.b==y.b) return x.c<y.c;
if(x.a==y.a) return x.b<y.b;
return x.a<y.a;
}
inline bool check(Node x,Node y){
return (x.a==y.a&&x.b==y.b&&x.c==y.c);
}
inline bool cmp1(Node x,Node y){
return x.t<y.t;
}
inline void cdq(int l,int r){
if(l==r) return;
int mid=(l+r)>>1;
cdq(l,mid);
cdq(mid+1,r);
int i=l,j=mid+1,k=l;
while(i<=mid&&j<=r){
if(po[i].b<=po[j].b){
update(po[i].c,po[i].cnt);
P[k++]=po[i++];
}
else{
po[j].ans+=query(po[j].c);
P[k++]=po[j++];
}
}
while(i<=mid){
update(po[i].c,po[i].cnt);
P[k++]=po[i++];
}
while(j<=r){
po[j].ans+=query(po[j].c);
P[k++]=po[j++];
}
for(ri t=l;t<=mid;++t) update(po[t].c,-po[t].cnt);
for(ri t=l;t<=r;++t) po[t]=P[t];
}
int main()
{
read(n);read(k);
for(ri i=1;i<=n;++i){
read(node[i].a);
read(node[i].b);
read(node[i].c);
node[i].t=i;
}
sort(node+1,node+n+1,cmp);
po[++tot]=node[1];
po[tot].t=tot;
po[tot].cnt=1;
to[1]=1;
for(ri i=2;i<=n;++i){
if(check(po[tot],node[i])) ++po[tot].cnt;
else{
po[++tot]=node[i];
po[tot].t=tot;
po[tot].cnt=1;
}
to[i]=tot;
}
cdq(1,tot);
sort(po+1,po+tot+1,cmp1);
for(ri i=1;i<=n;++i) Ans[node[i].t]=po[to[i]].ans+po[to[i]].cnt-1;
for(ri i=1;i<=n;++i) ++tong[Ans[i]];
for(ri i=0;i<n;++i) printf("%d\n",tong[i]);
return 0;
}
卢卡斯定理
#include<bits/stdc++.h>
using namespace std;
#define ri register int
#define ll long long
const int N = 300007;
ll T,m,n,p;
ll M[N];
void exgcd( ll a , ll b , ll &x , ll &y ){
if( !b ){
x = 1;
y = 0;
return;
}
ll x1,y1;
exgcd( b , a % b , x1 , y1 );
x = y1;
y = x1 - y1 * ( a / b );
}
inline ll inv( ll a ){
ll xx,yy;
exgcd( a , p , xx , yy );
xx = ( xx % p + p ) % p;
return xx;
}
inline ll C( ll n , ll m ){
return m > n ? 0 : M[ n ] * inv( M[ m ] ) % p * inv( M[ n - m ] ) % p;
}
ll lucas( ll n , ll m ){
return m ? lucas( n / p , m / p ) * C( n % p , m % p ) % p : 1LL;
}
int main()
{
scanf( "%lld" , &T );
while( T-- ){
scanf( "%lld%lld%lld" , &n , &m , &p );
M[ 0 ] = 1;
for( register ll i = 1 ; i <= n + m + 7 ; ++i )
M[ i ] = M[ i - 1 ] * i % p;
printf( "%lld\n" , lucas( n + m , m ) );
}
return 0;
}
excrt
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n,aa,bb;
ll x=0,y,lcm=1,t,gcd;
template<class T>inline void read(T &res){
static char ch;T flag=1;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') flag=-1;
res=ch-48;
while((ch=getchar())>='0'&&ch<='9') res=(res<<1)+(res<<3)+ch-48;
res*=flag;
}
ll slow_mul(ll x,ll k,ll mod){
if(x<=0&&k<=0) x=-x,k=-k;
else if(k<0) swap(x,k);
ll ans=0;x%=mod;
while(k){
if(k&1) ans=(ans+x)%mod;
k>>=1;
x=x*2%mod;
}
return ans;
}
ll exgcd(ll &x,ll &y,ll a,ll b){
if(b==0){
x=1;
y=0;
return a;
}
ll g=exgcd(x,y,b,a%b);
ll c=y;
y=x-a/b*y;
x=c;
return g;
}
int main()
{
read(n);
for(int i=1;i<=n;++i){
read(aa);read(bb);
gcd=exgcd(t,y,lcm,aa);
ll l=lcm/gcd*aa;
ll m=l/lcm;
t=slow_mul((bb-x)/gcd,t,m);
t=(t%m+m)%m;
x=x+t*lcm;
lcm=l;
x=(x%lcm+lcm)%lcm;
}
printf("%lld\n",x);
return 0;
}
快排
#include<bits/stdc++.h>
using namespace std;
int n,x,heap_size=0;
int heap[3000000];
void put(int d)
{
int now,next;
heap[++heap_size]=d;
now=heap_size;
while(now>1)
{
next=now/2;
if(heap[now]<heap[next])
swap(heap[now],heap[next]);
now=next;
}
}
int get()
{
int res=heap[1];
int now=1,next;
heap[1]=heap[heap_size--];
while(now*2<=heap_size)
{
next=2*now;
if(next<heap_size&&heap[next+1]<heap[next])
next++;
if(heap[now]<=heap[next])
return res;
else
{
swap(heap[now],heap[next]);
now=next;
}
}
return res;
}
int main()
{
//freopen("btree.in","r",stdin);
//freopen("btree.out","w",stdout);
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>x;
put(x);
}
for(int i=1;i<=n;i++)
cout<<get()<<" ";
return 0;
}
快速幂
// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define ri register int
#define ll long long
ll b,t,h,P;
char c[ 100007 ];
ll TenthPow( ll a ){
ll ans = 1,s = a;
while( t >= 0 ){
ll cnt = c[ t ] - '0',cur = s;
for( ri i = 1 ; i <= cnt ; ++i )
ans = ans * s % P;
for( ri i = 1 ; i < 10 ; ++i )
cur = cur * s % P;
s = cur;
ans %= P;
--t;
}
return ans;
}
int main()
{
cin>>b>>c>>P;
t = strlen( c );--t;
cout<<b<<"^"<<c<<" mod "<<P<<"="<<TenthPow( b );
return 0;
}
主席树
// luogu-judger-enable-o2
#include<cstdio>
#include<algorithm>
using namespace std;
#define oo 0x3f3f3f3f
#define mid ( ( l + r ) >> 1 )
#define ri register int
const int N = 200007,M = 4000000;
typedef long long ll;
int n,m,tot,num,pos,a[N],b[N],root[N],ls[M],rs[M],sum[M];
template<class T>
inline void read(T &res){
static char ch;T flag = 1;
while( ( ch = getchar() ) < '0' || ch > '9' ) if( ch == '-' ) flag = -1;
res = ch - 48;
while( ( ch = getchar() ) >= '0' && ch <= '9' ) res = res * 10 + ch - 48;
res *= flag;
}
inline void copy( int a , int b ){
ls[ a ] = ls[ b ];
rs[ a ] = rs[ b ];
sum[ a ] = sum[ b ] + 1;//由于插入了一个结点,所以要加1
}
int build( int l , int r ){
int s = ++tot;
if( l == r ) return s;
ls[ s ] = build( l , mid );
rs[ s ] = build( mid + 1 , r );
return s;
}
int modify( int l , int r , int s ){
int t = ++tot;
copy( t , s );
if( l == r ) return t;
if( pos <= mid ) ls[ t ] = modify( l , mid , ls[ t ] );
else rs[ t ] = modify( mid + 1 , r , rs[ t ] );
return t;
}
int query( int l , int r , int s , int ss , int k ){
int res = sum[ ls[ ss ] ] - sum[ ls[ s ] ];
if( l == r ) return b[ l ];
if( res >= k ) return query( l , mid , ls[ s ] , ls[ ss ] , k );
//多了,就递归到左子树去找k个
else return query( mid + 1 , r , rs[ s ] , rs[ ss ] , k - res );
//少了,就递归到右子树去再找k-res个
}
int main()
{
read( n );read( m );
for( ri i = 1 ; i <= n ; i++ ){
read( a[ i ] );
b[ i ] = a[ i ];
}
sort( b + 1 , b + n + 1 );
num = unique( b + 1 , b + n + 1 ) - b - 1;//最终返回了去重后的元素个数
root[ 0 ] = build( 1 , num );
for( ri i = 1 ; i <= n ; i++ ){
int l = 1,r = num;
while( l <= r ){
if( a[ i ] <= b[ mid ] ) r = mid - 1;
else l = mid + 1;
}pos = l;
root[ i ] = modify( 1 , num , root[ i - 1 ] );
}
for( ri i = 1 ; i <= m ; i++ ){
int l,r,k;read( l );read( r );read( k );
printf( "%d\n" , query( 1 , num , root[ l - 1 ] , root[ r ] , k ) );
}
return 0;
}
可持久化线段树
#include<cstdio>
using namespace std;
#define ri register int
#define mid ( ( l + r ) >> 1 )
const int N = 20000007,M = 1000007;
typedef long long ll;
int tot,ls[N],rs[N],root[M],a[M];
ll sum[N];
template<class T>
inline void read(T &res){
static char ch;T flag = 1;
while( ( ch = getchar() ) < '0' || ch > '9' ) if( ch == '-' ) flag = -1;
res = ch - 48;
while( ( ch = getchar() ) >= '0' && ch <= '9' ) res = res * 10 + ch - 48;
res *= flag;
}
inline void update( int s ){
sum[ s ] = sum[ ls[ s ] ] + sum[ rs[ s ] ];
}
inline void copy( int a , int b ){
ls[ a ] = ls[ b ];
rs[ a ] = rs[ b ];
sum[ a ] = sum[ b ];
}
inline int modify( int s , int l , int r , int ord , int x ){
int t = ++tot;
copy( t , s );
if( l == r ){
sum[ t ] = x;
return t;
}
if( ord <= mid ) ls[ t ] = modify( ls[ t ] , l , mid , ord , x );
else rs[ t ] = modify( rs[ t ] , mid + 1 , r , ord , x );
update( t );
return t;
}
inline int query( int s , int l , int r , int pos ){
if( l == r ){
return sum[ s ];
}
if( pos <= mid ) return query( ls[ s ] , l , mid , pos );
else return query( rs[ s ] , mid + 1 , r , pos );
}
void build( int s , int l , int r ){
if( l == r ) {
sum[ s ] = a[ l ];
return;
}
build( ls[ s ] = ++tot , l , mid );
build( rs[ s ] = ++tot , mid + 1 , r );
update( s );
}
int main()
{
int n,m;read( n );read( m );
for( ri i = 1 ; i <= n ; i++ ) read( a[ i ] );
build( root[ 0 ] = ++tot , 1 , n );
for( ri i = 1 ; i <= m ; i++ ){
int typ,NUM,pos;read( NUM );read( typ );read( pos );
if( typ == 1 ){
int val;read( val );
root[ i ] = modify( root[ NUM ] , 1 , n , pos , val );
}
else{
root[ i ] = root[ NUM ];
printf( "%d\n" , query( root[ NUM ] , 1 , n , pos ) );
}
}
return 0;
}
矩阵快速幂
#include<cstdio>
#include<cstring>
using namespace std;
#define ri register int
typedef long long ll;
const int N = 107;
const ll P = 1000000007;
ll n,k;
struct Matrix{
ll A[N][N];
inline void refresh(){
for( ri i = 1 ; i <= n ; ++i )
A[ i ][ i ] = 1;
}//建立单位矩阵
}cur,net;
Matrix operator *( const Matrix &x , const Matrix &y ){
Matrix z;
memset( z.A , 0 , sizeof( z.A ) );
for( int i = 1 ; i <= n ; ++i )
for( int j = 1 ; j <= n ; ++j )
for( int k = 1 ; k <= n ; ++k )
z.A[ i ][ j ] = ( z.A[ i ][ j ] + x.A[ i ][ k ] * y.A[ k ][ j ] % P ) % P;
return z;
}
inline Matrix qpow( Matrix a , ll k ){
Matrix ans;
ans.refresh();
while( k ){
if( k & 1 )
ans = ans * a;
a = a * a;
k = k >> 1;
}
return ans;
}
template<class T>inline void read(T &res){
static char ch;T flag = 1;
while( ( ch = getchar() ) < '0' || ch > '9' ) if( ch == '-' ) flag = -1;
res = ch - 48;
while( ( ch = getchar() ) >= '0' && ch <= '9' ) res = res * 10 + ch - 48;
res *= flag;
}
int main()
{
read( n );
read( k );
for( ri i = 1 ; i <= n ; ++i )
for( ri j = 1 ; j <= n ; ++j )
read( cur.A[ i ][ j ] );
net = qpow( cur , k );
for( ri i = 1 ; i <= n ; ++i ){
for( ri j = 1 ; j <= n ; ++j )
printf( "%lld " , net.A[ i ][ j ] );
putchar( '\n' );
}
return 0;
}
后缀自动机
#include<bits/stdc++.h>
using namespace std;
#define ri register int
#define ll long long
const int N=2000007;
int root=1,len,ndnum=1,last=1;
char s[N>>1];
struct Node{
int par,go[26];
ll len;
}node[N];
struct Edge{
int to,next;
}e[N];
int tot,head[N];
ll f[N],ans;
template<class T>inline void read(T &res){
static char go;T flag=1;
while((go=getchar())<'0'||go>'9') if(go=='-') flag=-1;
res=go-48;
while((go=getchar())>='0'&&go<='9') res=(res<<1)+(res<<3)+go-48;
res*=flag;
}
inline int New(){
int p=++ndnum;
memset(node[p].go,0,sizeof(node[p].go));
return p;
}
inline void Add(int w){
int x=New(),tmp=last;
f[x]=1;
node[x].len=node[last].len+1;
while(tmp&&!node[tmp].go[w]){
node[tmp].go[w]=x;
tmp=node[tmp].par;
}
if(!tmp) node[x].par=root;
else{
int B=node[tmp].go[w];
if(node[B].len==node[tmp].len+1) node[x].par=B;
else{
int nB=New();
node[nB]=node[B];
node[nB].len=node[tmp].len+1;
node[B].par=node[x].par=nB;
while(tmp&&node[tmp].go[w]==B){
node[tmp].go[w]=nB;
tmp=node[tmp].par;
}
}
}
last=x;
}
inline void add(int from,int to){
e[++tot].to=to;
e[tot].next=head[from];
head[from]=tot;
}
void dfs(int u){
for(ri i=head[u];i;i=e[i].next){
int v=e[i].to;
dfs(v);
f[u]+=f[v];
}
if(f[u]!=1) ans=max(ans,f[u]*node[u].len);
}
int main()
{
scanf("%s",s);
len=strlen(s);
for(ri i=0;i<len;++i) Add(s[i]-'a');
for(ri i=2;i<=ndnum;++i) add(node[i].par,i);
dfs(1);
printf("%lld\n",ans);
return 0;
}
后缀数组
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define ri register int
#define ll long long
const int N=1000007;
int n,up=255;
int sa[N];
int len;
/*排名为 i 的后缀的位置,实质上就对应着这个后缀,
因为一个后缀对应且仅对应一个起始位置*/
int rk[N];
//从 i 位置开始的后缀的排名,排序的过程用不上,在求height数组中有用
/*转化关系:sa[rk[i]]=i;rk[sa[i]]=i;
参考 log2(2^x)=x , 2^(log2(x))=x 来理解*/
int fir[N];
// i 位置开始的后缀用于排序的第一关键字的排名值
int sec[N];
//第二关键字排名为 i 的后缀起始位置
int cnt[N];
// i 号元素出现了多少次,其实就是桶
int tmp[N];
//用于更新fir时,保存当前的fir
char s[1000007];
void get_sa(){
for(ri i=0;i<len;++i) fir[i+1]=s[i];
// for(ri i=0;i<=up;++i) cnt[i]=0;//清空桶
for(ri i=1;i<=len;++i) ++cnt[fir[i]];
//存入到桶里
for(ri i=1;i<=up;++i) cnt[i]+=cnt[i-1];
//做一下前缀和,cnt 中存的就是排名了
for(ri i=len;i>=1;--i) sa[cnt[fir[i]]--]=i;
//得到排名,第一关键字相同时,位置靠后的排名靠后
int k=1;
while(k<len){
ri j=0;
for(ri i=len-k+1;i<=len;++i) sec[++j]=i;
//把没有第二部分串的后缀的第二关键字按照序号排名
for(ri i=1;i<=len;++i)
if(sa[i]-k>=1)
sec[++j]=sa[i]-k;
//得到有第二部分串的后缀的第二关键字
for(ri i=1;i<=up;++i) cnt[i]=0;
//再清空桶
for(ri i=1;i<=len;++i) ++cnt[fir[sec[i]]];
for(ri i=1;i<=up;++i) cnt[i]+=cnt[i-1];
for(ri i=len;i>=1;--i)
sa[cnt[fir[sec[i]]]--]=sec[i];
/*依旧仿照上面,不过是以 sec[i] 为下标
用中文来说就是(高能预警):
按从大到小的顺序枚举第二关键字的排名,以'第二关键
字的排名为 i 的后缀'的第一关键字的排名,记录下这
个后缀的位置( sec[i] 就是这个后缀的位置诶)
(''是方便断句)
酱可以保证是以第一和第二关键字排的序且排名各不相
同 */
swap(fir,tmp);
/*交换 fir 和 tmp 数组,这样在接下来的操作中,fir 被更
新为下一次排序的 fir ,而 tmp 就保存这次的 fir*/
j=0;
fir[sa[1]]=++j;
for(ri i=2;i<=len;++i){
if(sa[i]+k<=len&&sa[i-1]+k<=len&&
tmp[sa[i]]==tmp[sa[i-1]]&&
tmp[sa[i]+k]==tmp[sa[i-1]+k])
fir[sa[i]]=j;
/*判断下一次第一关键字是否相同的条件,两者都必须
拥有第二部分串且它们的第一关键字和第二关键字相同*/
else fir[sa[i]]=++j;
}
if(j==len) break;
up=j;//cnt 的上界变为了 j
k<<=1;
}
}
int height[N];
//排名相邻( i 和 i-1 )的两个后缀的最长公共前缀的长度,有用的一个数组
//int h[N];虚假的数组,定义:h[i]=height[rk[i]]
//利用性质:h[i]>=h[i-1]-1 来求 height[i]
void get_h(){
for(ri i=1;i<=len;++i) rk[sa[i]]=i;
int ch=0;
for(ri i=1;i<=len;++i){
int t=sa[rk[i]-1];
while(s[t+ch]==s[i+ch]) ++ch;
height[rk[i]]=ch;
ch=max(0,ch-1);//性质
}
}
int main()
{
scanf("%s",s);
len=strlen(s);
get_sa();
// for(ri i=1;i<=len;++i) printf("%d ",sa[i]);
get_h();
return 0;
}
哈希表
const int SZ=1991107;
struct hash_map{
struct data{
long long u;
int v,nex;
};
data e[SZ<<1];
int h[SZ],cnt;
int hash(long long u) {return u % SZ;}
int& operator[](long long u){
int hu=hash(u);
for(int i=h[hu];i;i=e[i].nex)
if(e[i].u==u)
return e[i].v;
return e[++cnt]=(data){u,-1,h[hu]},h[hu]=cnt,e[cnt].v;
}
hash_map(){
cnt=0;
memset(h,0,sizeof(h));
}
void clear(){
cnt=0;
memset(h,0,sizeof(h));
}
}mp;
割点
#include<cstdio>
using namespace std;
#define ri register int
#define min(a,b) (a<b?a:b)
const int N = 100007;
int n,m,tot,head[N],dfn[N],low[N];
bool cp[N];
struct Edge{
int to,next;
}e[N<<1];
inline void add( int from , int to );
template<class T>inline void read(T &res);
inline void tarjan( int u , int root ){
int son = 0;
dfn[ u ] = low[ u ] = ++tot;
for( ri i = head[ u ] ; i ; i = e[ i ].next ){
int v = e[ i ].to;
if( !dfn[ v ] ){
tarjan( v , root );
low[ u ] = min( low[ u ] , low[ v ] );
if( root == u ) ++son;//记录根结点的儿子
if( low[ v ] >= dfn[ u ] && u != root )
cp[ u ] = true;//当v的追溯值大于u时,u就是割点
}
else low[ u ] = min( low[ u ] , dfn[ v ] );
}
if( u == root && son >= 2 )
cp[ u ] = true;
}
int main()
{
read( n );read( m );
for( ri i = 1 ; i <= m ; ++i ){
int u,v;
read( u );read( v );
add( u , v );add( v , u );
}
tot = 0;
for( ri i = 1 ; i <= n ; ++i )
if( !dfn[ i ] )
tarjan( i , i );
int cnt = 0;
for( ri i = 1 ; i <= n ; ++i )
if( cp[ i ] )
++cnt;
printf( "%d\n" , cnt );
for( ri i = 1 ; i <= n ; ++i )
if( cp[ i ] )
printf( "%d " , i );
return 0;
}
template<class T>inline void read(T &res){
static char ch;T flag = 1;
while( ( ch = getchar() ) < '0' || ch > '9' ) if( ch == '-' ) flag = -1;
res = ch - 48;
while( ( ch = getchar() ) >= '0' && ch <= '9' ) res = res * 10 + ch - 48;
res *= flag;
}
inline void add( int from , int to ){
e[ ++tot ].to = to;
e[ tot ].next = head[ from ];
head[ from ] = tot;
}
负环
#include<vector>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
#define oo 0x3f3f3f3f
#define RI register int
#define N 2009
typedef long long ll;
int T,n,m,s,dis[ N ],cnt[ N ];
//bool vis[ N ];
vector<int> e[ N ],d[ N ];
queue<int> q;//竞赛用了C++,能使用万能头文件和STL
template<class T>
inline void read(T &res){
static char ch;T flag = 1;
while( ( ch = getchar() ) < '0' || ch > '9' )
if( ch == '-' ) flag = -1;
res = ch - 48;
while( ( ch = getchar() ) >= '0' && ch <= '9' )
res = res * 10 + ch - 48;
res *= flag;
}
bool SPFA(){
memset( dis , oo , sizeof( dis ) );dis[ s ] = 0;
// memset( vis , false , sizeof( vis ) );
memset( cnt , 0 , sizeof( cnt ) );
q.push( s );
while( !q.empty() ){
int u = q.front();q.pop();
cnt[ u ]++;if( cnt[ u ] > n ) return true;//存在负环
for( RI i = 0 ; i < e[ u ].size() ; i++ )
if( dis[ e[ u ][ i ] ] > dis[ u ] + d[ u ][ i ] ){
dis[ e[ u ][ i ] ] = dis[ u ] + d[ u ][ i ];
q.push( e[ u ][ i ] );
}
}
return false;
}
inline void clear( queue<int>& q ) {
queue<int> empty;
swap( empty, q );
}
int main()
{
read( T );
while( T-- ){
for( RI i = 1 ; i <= n ; i++ ){e[ i ].clear();d[ i ].clear();}
clear( q );
read( n );read( m );
for( RI i = 1 ; i <= m ; i++ ){
int x,y,z;read( x );read( y );read( z );
if( z < 0 ){
e[ x ].push_back( y );d[ x ].push_back( z );
continue;
}
e[ x ].push_back( y );d[ x ].push_back( z );
e[ y ].push_back( x );d[ y ].push_back( z );
}
s = 1;
// for( register int i = 1 ; i <= n ; i++ ){
// e[ 0 ].push_back( i );
// d[ 0 ].push_back( 0 );
// }
if( SPFA() ) printf( "YE5\n" );
else printf( "N0\n" );
}
return 0;
}
二分图匹配
// luogu-judger-enable-o2
#include<cstdio>
using namespace std;
#define ri register int
#define iv inline void
const int N = 1000010,XN = 2009;
int n,m,E,tot = 0,ans = 0,vis[ XN ],head[ XN ],match[ XN ];
struct Edge{int to,next;}e[ N ];
iv add( int from , int to ){
e[ ++tot ].next = head[ from ];
e[ tot ].to = to;head[ from ] = tot;
}
bool dfs( int x , int timer ){
if( vis[ x ] == timer ) return false;//有环
vis[ x ] = timer;
for( ri j = head[ x ] ; j ; j = e[ j ].next )
if( !match[ e[ j ].to ] || dfs( match[ e[ j ].to ] , timer ) ){
match[ e[ j ].to ] = x;
return true;
}
return false;
}
template<class T>
inline void read(T &res){
static char ch;T flag = 1;
while( ( ch = getchar() ) < '0' || ch > '9' )
if( ch == '-' ) flag = -1;
res = ch - 48;
while( ( ch = getchar() ) >= '0' && ch <= '9' )
res = res * 10 + ch - 48;
res *= flag;
}
int main(){
read( n );read( m );read( E );
for( ri i = 1 ; i <= E ; i++ ){
int a,b;read( a );read( b );
if( a > n || b > m ) continue;
add( a , b + n );
}
for( ri i = 1 ; i <= n ; i++ ) if( dfs( i , i ) ) ans++;
printf( "%d\n" , ans );
return 0;
}
堆
#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
#define N 1000005
template<class T>
inline void read(T &res)
{
static char ch;
T flag = 1;
while( ( ch = getchar() ) < '0' || ch > '9' )
if( ch == '-' )
flag = -1;
res = ch - 48;
while( ( ch = getchar() ) >= '0' && ch <= '9' )
res = res * 10 + ch - 48;
res *= flag;
}
struct dui{//小根堆
int n[ N << 2 ];
int cnt;
inline int size(){
return cnt;
}
inline int top(){
return n[ 1 ];
}
inline void push( int x ){
n[ ++cnt ] = x;
int ord = cnt;
while( n[ ord ] < n[ ord >> 1] ){
swap( n[ ord ] , n[ ord >> 1] );
ord = ord >> 1;
}
}
inline void pop(){
swap( n[ cnt ] , n[ 1 ] );
cnt--;
int ord = 1;
while( ( ord << 1 ) <= cnt ){//保证有儿子
int next = ( ord << 1 );
if( next < cnt && n[ next + 1 ] < n[next] )
next++;
if( n[ ord ] <= n[ next ] )
break;
swap( n[ ord ] , n[ next ] );
ord = next;
}
}
inline bool empty(){
if( !cnt )
return true;
return false;
}
dui(){
cnt = 0;
}
}q;
int main()
{
int n;
cin>>n;
for( register int i = 1 ; i <= n ; i ++ ){
int x;
read( x );
switch( x ){
case 1:{
int y;
read( y );
q.push( y );
break;
}
case 2:{
printf( "%d\n" , q.top() );
break;
}
case 3:{
q.pop();
break;
}
}
}
return 0;
}
堆优化dij
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define oo 0x3f3f3f3f
#define N 200010
int n,m,start,eeee,tot = 0,dis[ N / 2 ],head[ N / 2 ];
bool vis[ N / 2 ];
struct Node{
int to,dis;
};
struct node{
int to,next,dis;
}e[ N ];
struct dui{
Node n[ N * 4 ];
int cnt;
inline int size(){
return cnt;
}
inline Node top(){
return n[ 1 ];
}
inline void push( Node x ){
n[ ++cnt ] = x;
int ord = cnt;
while( n[ ord ].dis < n[ ord >> 1].dis ){
swap( n[ ord ] , n[ ord >> 1] );
ord = ord >> 1;
}
}
inline void pop(){
swap( n[ cnt ] , n[ 1 ] );
cnt--;
int ord = 1;
while( ord * 2 <= cnt ){
int next = ord * 2 ;
if( next < cnt && n[ next + 1 ].dis < n[ next ].dis )
next++;
if( n[ ord ].dis <= n[ next ].dis )
break;
swap( n[ ord ] , n[ next ] );
ord = next;
}
}
inline bool empty(){
if( !cnt ) return true;
return false;
}
dui(){cnt=0;}
}q;//小根堆
template<class T>
inline void read(T &res){
static char ch;T flag = 1;
while( ( ch = getchar() ) < '0' || ch > '9' )
if( ch == '-' ) flag = -1;
res = ch - 48;
while( ( ch = getchar() ) >= '0' && ch <= '9' )
res = res * 10 + ch - 48;
res *= flag;
}
inline void add( int from , int to , int Distance ){
e[ ++tot ].to = to;
e[ tot ].next = head[ from ];
e[ tot ].dis = Distance;
head[ from ] = tot;
}
int main()
{
read( n );read( m );read( start );read(eeee);
for( register int i = 1 ; i <= m ; i++ ){
int x,y,d;
read( x );read( y );read( d );
add( x , y , d );
}
memset( vis , false , sizeof( vis ) );
memset( dis , oo , sizeof( dis ) );
dis[ start ] = 0;
Node s = { start , 0 };q.push( s );
while( !q.empty() ){
int u = q.top().to,d = q.top().dis;q.pop();
if( vis[ u ] ) continue;
vis[ u ] = true;
for( register int i = head[ u ] ; i ; i = e[ i ].next )
if( !vis[ e[ i ].to ] && dis[ e[ i ].to ] > dis[ u ] + e[ i ].dis ){
dis[ e[ i ].to ] = dis[ u ] + e[ i ].dis;
Node p = { e[ i ].to , dis[ e[ i ].to ] };
q.push( p );
}
}
// for( register int i = 1 ; i <= n ; i++ )
// printf( "%d " , dis[ i ] );
printf("%d\n",dis[eeee]);
return 0;
}
并查集
#include<bits/stdc++.h>
using namespace std;
int father[100005];
void unionn(int x,int y)//集合合并
{
father[y]=x;
}
int find(int x)//寻找根结点编号并压缩路径
{
if(father[x]!=x)
father[x]=find(father[x]);//将x的最近父结点更新为根结点
return father[x];
}
bool judge(int x,int y)//判断两个元素是否属于一个集合
{
x=find(x);
y=find(y);
if(x==y)
return true;
else
return false;
}
void mergee(int x,int y)
{
int r1=find(x);
int r2=find(y);//找到元素的祖先
if(r1!=r2)
unionn(r1,r2);//集合合并
//直接将 x的根结点r1 更新为 y的根结点r2 的根结点
//,相当于将以r2为代表的集合
//放到以r1为代表的集合内,并删除集合r2
}
void search(int x1,int y1)
{
if(judge(x1,y1))//判断元素是否在同一个集合
printf("Y\n");
else
printf("N\n");
}
int main()
{
//freopen("relation.in","r",stdin);
//freopen("relation.out","w",stdout);
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
father[i]=i;//初始化,分离集合,每个结点的父结点是他自己
for(int i=1;i<=m;i++)
{
int z,x,y;
scanf("%d%d%d",&z,&x,&y);
if(z==1)//合并
mergee(x,y);
else if(z==2)
search(x,y);
}
return 0;
}
Treap
#include<cstdio>
#include<cstdlib>
#include<ctime>
using namespace std;
const int N=200000;
int n,ndnum,T,root=0;
struct Treap{
int size,cnt,ls,rs,dat,val;
#define size(x) a[x].size
#define cnt(x) a[x].cnt
#define ls(x) a[x].ls
#define rs(x) a[x].rs
#define val(x) a[x].val
#define dat(x) a[x].dat
}a[N];
template<class T>inline void read(T &res){
static char ch;T flag=1;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') flag=-1; res=ch-48;
while((ch=getchar())>='0'&&ch<='9') res=(res<<1)+(res<<3)+ch-48; res*=flag;
}
inline int New(int x){
a[++ndnum].val=x;
a[ndnum].dat=rand();
a[ndnum].cnt=a[ndnum].size=1;
return ndnum;
}
inline void update(int p){
a[p].size=a[ls(p)].size+a[rs(p)].size+a[p].cnt;
}
inline void Zig(int &p){
int q=ls(p);
ls(p)=rs(q);
rs(q)=p;
p=q;
update(p);
update(rs(p));
}
inline void Zag(int &p){
int q=rs(p);
rs(p)=ls(q);
ls(q)=p;
p=q;
update(p);
update(ls(p));
}
void Insert(int &p,int x){
if(p==0) p=New(x);
else if(x==val(p)) ++cnt(p);
else if(x<a[p].val){
Insert(ls(p),x);
if(dat(p)<dat(ls(p))) Zig(p);
}
else if(x>a[p].val){
Insert(rs(p),x);
if(dat(p)<dat(rs(p))) Zag(p);
}
update(p);
}
void Del(int &p,int x){
if(p==0) return;
if(x==val(p)){
if(cnt(p)>1) --cnt(p);
else if(ls(p)||rs(p)){
if(rs(p)==0||dat(ls(p))>dat(rs(p))){
Zig(p);
Del(rs(p),x);
}
else{
Zag(p);
Del(ls(p),x);
}
}
else p=0;
}
else x<val(p)?Del(ls(p),x):Del(rs(p),x);
update(p);
}
int Rank(int p,int x){
if(x==val(p)) return size(ls(p))+1;
if(x<val(p)) return Rank(ls(p),x);
else return size(ls(p))+cnt(p)+Rank(rs(p),x);
}
int Search(int p,int rk){
if(rk<=size(ls(p))) return Search(ls(p),rk);
if(rk<=size(ls(p))+cnt(p)) return val(p);
else return Search(rs(p),rk-size(ls(p))-cnt(p));
}
inline int Pre(int x){
int p=root,ans=-0x7fffffff;
while(p){
if(val(p)<x&&val(p)>ans)
ans=val(p);
if(x==val(p)){
p=ls(p);
while(p){
ans=val(p);
p=rs(p);
}
break;
}
else if(x<val(p)) p=ls(p);
else if(x>val(p)) p=rs(p);
}
return ans;
}
inline int Next(int x){
int p=root,ans=0x7fffffff;
while(p){
if(val(p)>x&&val(p)<ans)
ans=val(p);
if(x==val(p)){
p=rs(p);
while(p){
ans=val(p);
p=ls(p);
}
break;
}
else if(x<val(p)) p=ls(p);
else if(x>val(p)) p=rs(p);
}
return ans;
}
int main()
{
srand(time(0));
read(T);
while(T--){
int opt,x;
read(opt);read(x);
if(opt==1) Insert(root,x);
else if(opt==2) Del(root,x);
else if(opt==3) printf("%d\n",Rank(root,x));
else if(opt==4) printf("%d\n",Search(root,x));
else if(opt==5) printf("%d\n",Pre(x));
else if(opt==6) printf("%d\n",Next(x));
}
return 0;
}
st表
#include<bits/stdc++.h>
using namespace std;
#define N 100050
int n,m,l;
int a[ N ][ 25 ],lg2[ N + 50 ];
inline int max( int x , int y ){
return x > y ? x : y;
}
inline int min( int x , int y ){
return x < y ? x : y;
}
template<class T>
inline void read(T &res){
static char ch;
T flag = 1;
while( ( ch = getchar() ) < '0' || ch > '9' )
if( ch == '-' )
flag = -1;
res = ch - 48;
while( ( ch = getchar() ) >= '0' && ch <= '9' )
res = res * 10 + ch - 48;
res *= flag;
}
inline int maxn( int l , int r ){
int k = lg2[ r - l + 1 ];
return max( a[ l ][ k ] , a[ r - ( 1 << k ) + 1 ][ k ] );
}
int main()
{
read( n ),read( m );
for( register int i = 1 ; i <= n ; i++ )
read( a[ i ][ 0 ] );
for( register int i = 2 ; i <= 100000 ; i++ )
lg2[ i ] = lg2[ i / 2 ] + 1;
int l = lg2[ n ] + 1;
for( register int j = 1 ; j <= l ; j++ )
for( register int i = 1 ; i + ( 1 << j ) - 1 <= n ; i++ )
a[ i ][ j ] = max( a[ i ][ j - 1 ] , a[ i + ( 1 << ( j - 1 ) ) ][ j - 1 ] );
for( register int i = 1 ; i <= m ; i++ ){
int x,y;
read( x ),read( y );
printf( "%d\n" , maxn( x , y ) );
}
return 0;
}
Splay
#include<cstdio>
using namespace std;
#define ri register int
#define ll long long
const int N=200007;
int n;
template<class T>inline void read(T &res){
static char son;T flag=1;
while((son=getchar())<'0'||son>'9') if(son=='-') flag=-1;
res=son-48;
while((son=getchar())>='0'&&son<='9') res=(res<<1)+(res<<3)+son-48;
res*=flag;
}
class Splay{
public:
int root,tot=0,fa[N],size[N],cnt[N],val[N],son[N][2];
private:
void update(int p){
size[p]=size[son[p][0]]+size[son[p][1]]+cnt[p];
}
int check(int p){
return p==son[fa[p]][1];
}
void rotate(int p){
int f=fa[p],ff=fa[f],k=check(p),kk=check(f),sp=son[p][k^1];
son[p][k^1]=f;fa[f]=p;
son[f][k]=sp;fa[sp]=f;
son[ff][kk]=p;fa[p]=ff;
update(f);update(p);
}
void splay(int p,int goal){
if(p==goal) return;//易忘
while(fa[p]!=goal){
int f=fa[p],ff=fa[f];
if(ff!=goal){
if(check(p)==check(f)) rotate(f);
else rotate(p);
}
rotate(p);
}
if(goal==0) root=p;//易忘
}//把p Splay到goal的儿子
void find(int x){
int cur=root;
while(son[cur][x>val[cur]]&&x!=val[cur])
cur=son[cur][x>val[cur]];
splay(cur,0);
}
public:
int rank(int x){
find(x);
return size[son[root][0]]+1;
}
void insert(int x){
int cur=root,p=0;//p是cur的父亲
while(cur&&x!=val[cur]){
p=cur;
cur=son[cur][x>val[cur]];
}
if(cur) ++cnt[cur];//找到了x
else{
cur=++tot;
// son[cur][0]=son[cur][1]=0;
fa[cur]=p;
val[cur]=x;
cnt[cur]=size[cur]=1;//要赋全
if(p) son[p][x>val[p]]=cur;//一定要判断
}
splay(cur,0);
}
int pre(int x){
find(x);
if(val[root]<x) return root;
int p=son[root][0];
while(son[p][1]) p=son[p][1];
return p;
}//记得返回的是位置而不是实际的值
int nxt(int x){
find(x);
if(val[root]>x) return root;
int p=son[root][1];
while(son[p][0]) p=son[p][0];
return p;
}
void del(int x){
int pr=pre(x),nt=nxt(x);
splay(pr,0);splay(nt,pr);
int p=son[nt][0];
if(cnt[p]>1){
--cnt[p];
splay(p,0);
}
else son[nt][0]=0;
update(nt);update(root);
}
int search(int rk){
int p=root;
while(1){
if(son[p][0]&&rk<=size[son[p][0]]) p=son[p][0];//一定要判断是否有儿子
else if(rk>size[son[p][0]]+cnt[p]){
rk-=size[son[p][0]]+cnt[p];
p=son[p][1];//注意顺序
}
else{
splay(p,0);
return p;
}
}
}
}Tree;
int main()
{
Tree.insert(2147483647);
Tree.insert(-2147483647);
read(n);
while(n--){
int opt,x;
read(opt);
read(x);
switch(opt){
case 1:{
Tree.insert(x);
break;
}
case 2:{
Tree.del(x);
break;
}
case 3:{
printf("%d\n",Tree.rank(x)-1);
break;
}
case 4:{
printf("%d\n",Tree.val[Tree.search(x+1)]);
break;
}
case 5:{
printf("%d\n",Tree.val[Tree.pre(x)]);
break;
}
case 6:{
printf("%d\n",Tree.val[Tree.nxt(x)]);
break;
}
}
}
return 0;
}
nim博弈
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int T,n,x,y;
template<class T>inline void read(T &res){
static char ch;T flag=1;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') flag=-1; res=ch-48;
while((ch=getchar())>='0'&&ch<='9') res=(res<<1)+(res<<3)+ch-48; res*=flag;
}
int main()
{
read(T);
while(T--){
read(n);
x=0;
while(n--){
read(y);
x^=y;
}
printf(x?"Yes\n":"No\n");
}
return 0;
}