模板整理1

数据结构

ST表

#include<bits/stdc++.h>

using namespace std;

const int maxn = 1e5 + 5;

int n,m;
int ma[20][maxn],lo[maxn];
void init(){
	for(int j = 1;(1<<j) <= n; ++ j){
		for(int i = 1;i <= n-(1<<j)+1; ++ i){//注意顺序 ,注意范围 
			ma[j][i] = max(ma[j-1][i],ma[j-1][i+(1<<(j-1))]);
		}
	}
}

void readdata(){
	read(n);read(m);
	lo[0] = -1;//初始化 
	for(int i = 1;i <= n; ++ i) read(ma[0][i]),lo[i] = lo[i/2]+1;;
}

void work(){
	while(m -- ){
		int l,r;read(l);read(r);
		int j = lo[r-l+1];
		int ans = max(ma[j][l],ma[j][r-(1<<j)+1]);
		put(ans);putchar('\n');
	}
}

int main(){
	readdata();
	init();
	work();
	return 0;
}

单队

#include<bits/stdc++.h>

using namespace std;

const int maxn = 2e6 + 5;

int n,l,r,m;
int q[maxn],a[maxn];
void readdata(){
	read(n);read(m);
}

void work(){
	for(int i = 1;i <= n; ++ i){
		
		read(a[i]);
		
		while(l < r && i - q[l] > m) l++;
		
		if(l >= r) puts("0");
		else put(a[q[l]]),putchar('\n');
		
		while(l < r && a[q[r - 1]] >= a[i]) r--;//>= 
		q[r++] = i;
	}
}

int main(){
//	file();
	readdata();
	work();
	return 0;
}

LCA

#include<bits/stdc++.h>

using namespace std;

const int maxn = 5e5 + 5;
const int maxm = 5e5 + 5;

int n,m,top[maxn],size,first[maxn],s;
int cnt[maxn],father[maxn];
int dep[maxn];

struct Edge{
	int v,nt;
}edge[maxm << 1];

void eadd(int u,int v){
	edge[++size].v = v;
	edge[size].nt = first[u];
	first[u] = size;
}

void dfs(int u,int fa,int d){
	top[u] = u;father[u] = fa;
	int son = 0,mcnt = 0;
	cnt[u] = 1;dep[u] = d;
	for(int i = first[u];i;i = edge[i].nt){
		int v = edge[i].v;
		if(v == fa) continue;
		dfs(v,u,d + 1);
		cnt[u] += cnt[v];
		if(cnt[v] > mcnt){
			mcnt = cnt[v];
			son = v;
		}
	}
	if(son) top[son] = u;
	
}

int find(int x){
	return top[x] == x ? x : top[x] = find(top[x]);
}

int LCA(int x,int y){
	if(find(x) == find(y)) return dep[x]<dep[y]?x:y;
	else return dep[top[x]]<dep[top[y]]?LCA(x,father[top[y]]):LCA(father[top[x]],y);
}

int main(){
	read(n);read(m);read(s);
	for(int i = 1;i < n; ++ i){
		int u,v;
		read(u);read(v);
		eadd(u,v);eadd(v,u);
	}
	dfs(s,0,1);
	
	for(int i = 1;i <= m; ++ i){
		int u,v;
		read(u);read(v);
		int ans = LCA(u,v);
		put(ans);
		puts("");
	}
	return 0;
}

#include<bits/stdc++.h>
#define M 500002
#define N 500002
#define Max(x,y) (x)>(y)?(x):(y)
#define Min(x,y) (x)<(y)?(x):(y)
#define up(i,l,r) for(int i=l;i<=r;++i)
#define down(i,l,r) for(int i=r;i>=l;--i)

using namespace std;

static int n,m,s,head[N],father[N][20],size=0,maxdep,dep[N],step;

struct Edge
{
	int v,nt;
};
static Edge edge[N<<1];
void eadd(int u,int v)
{
	edge[++size].v=v;
	edge[size].nt=head[u];
	head[u]=size;
}

void readdata()
{
	n=read(); m=read(); s=read();
	up(i,1,n-1)
	{
		int x=read(),y=read();
		eadd(x,y);
		eadd(y,x);
	}
}

void dfs(int u)
{
	for(int i=head[u];i;i=edge[i].nt)
	{
		int v=edge[i].v;
		if(v==father[u][0]) continue;
		dep[v]=dep[u]+1;
		maxdep=Max(maxdep,dep[v]);
		father[v][0]=u;
		dfs(v);
	}
}

void doubling()
{
	up(j,1,step)
	{
		int k=j-1;
		up(i,1,n)
	    	if(father[i][k]) father[i][j]=father[father[i][k]][k];
	}
	    
}

int lca(int u,int v)
{
	if(dep[u]<dep[v]) swap(u,v);
	down(i,0,step)
	{
		if(father[u][i]&&dep[father[u][i]]>=dep[v]) u=father[u][i];
		if(u==v) return u;
	}
	down(i,0,step)
	{
		if(father[u][i]!=father[v][i]) {u=father[u][i]; v=father[v][i];}
	}
	return father[u][0]; 
}

void work()
{
	dep[s]=1;
	dfs(s);
	step=log(maxdep)/log(2);
	doubling();
	up(z,1,m)
	{
		int a=read(),b=read();
		put(lca(a,b));
	}
}

int main()
{
//	init();
    readdata();
    work();
    return 0;
}

#include<bits/stdc++.h>
#define N 500002
#define M 500002
#define Max(x,y) (x)>(y)?(x):(y)
#define Min(x,y) (x)<(y)?(x):(y)
#define up(i,l,r) for(int i=l;i<=r;++i)
#define down(i,l,r) for(int i=r;i>=l;--i)

using namespace std;

static int head[N],size,n,m,s,dfn[N],ct,first[N],stmin[N<<1][20],number;

struct Edge
{
	int v,nt;
};
static Edge edge[N<<1];

void eadd(int u,int v)
{
	edge[++size].v=v;
	edge[size].nt=head[u];
	head[u]=size;
}

void readdata()
{
	n=read(); m=read(); s=read();
	up(i,1,n-1)
	{
		int x=read(),y=read();
		eadd(x,y);
		eadd(y,x);
	}
}

void dfs(int u,int father)
{
	int num=++number;
	dfn[num]=u;
	first[u]=++ct;
	stmin[ct][0]=num;
	for(int i=head[u];i;i=edge[i].nt)
	{
		int v=edge[i].v;
		if(v==father) continue;
		dfs(v,u);
		stmin[++ct][0]=num;
	}
}

void Sparce_Table()
{
	for(int j=1;(1<<j)<=ct;++j)//log有误差 
	{
		int x=j-1;
		up(i,1,ct-(1<<j)+1)
	    	stmin[i][j]=Min(stmin[i][x],stmin[i+(1<<x)][x]);//注意+1的条件 
	}
}

int lca(int u,int v)
{
	int low=Min(first[u],first[v]);
	int high=Max(first[u],first[v]);
	int step1=(int)(log(high-low+1)/log(2));//一定打括号 
	return dfn[Min(stmin[low][step1],stmin[high-(1<<step1)+1][step1])];//注意+1的条件 
}

void work()
{
	dfs(s,0);
	Sparce_Table();
	up(z,1,m)
	{
		int a=read(),b=read();
		put(lca(a,b));
		putchar('\n');
	}
}

int main()
{
//	init();
	readdata();
	work();
	return 0;
}

#include<cstdio>
#define MAXN 
#define MAXQ 
int n,Q,heade[MAXN],headq[MAXN],fa[MAXN],lca[MAXQ],dis[MAXN],cnt;
bool vis[MAXN];
struct edge
{
    int v,next,val;
}e[MAXN*2];
struct query
{
    int u,v,next;
}q[MAXQ*2];
void adde(int x,int y,int z)
{
    e[++cnt].v=y;
    e[cnt].next=heade[x];
    heade[x]=cnt;
    e[cnt].val=z;
}
void addq(int x,int y)
{
    q[++cnt].u=x;
    q[cnt].v=y;
    q[cnt].next=headq[x];
    headq[x]=cnt;
}
int getfa(int x)//并查集路径压缩
{
    return fa[x]=x==fa[x]?x:getfa(fa[x]);
}
int getdis(int i)//计算路径长度
{
    return dis[q[i<<1].u]+dis[q[i<<1].v]-2*dis[lca[i]];
}
void Tarjan(int u)
{
    fa[u]=u;
    vis[u]=true;
    for(int i=heade[u];i;i=e[i].next)
    {
        int v=e[i].v;
        if(!vis[v])
        {
            dis[v]=dis[u]+e[i].val;
            Tarjan(v);
            fa[v]=u;
        }
    }
    for(int i=headq[u];i;i=q[i].next)//处理询问
    {
        int v=q[i].u==u?q[i].v:q[i].u;
        if(vis[v])lca[i>>1]=getfa(fa[v]);
    }
}
int main()
{
    scanf("%d",&n);
    int x,y,z;
    for(int i=1;i<n;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        adde(x,y,z);
        adde(y,x,z);
    }
    cnt=1;
    scanf("%d",&Q);
    for(int i=1;i<=Q;i++)
    {
        scanf("%d%d",&x,&y);
        addq(x,y);
        addq(y,x);
    }
    Tarjan(1);
    for(int i=1;i<=Q;i++)
    {
        printf("%d\n",getdis(i));
    }
    return 0;
}

并查集

以食物链为例
边带权:


//有三种关系,且是有向的
//那就默认权值的方向指向父亲
//现在就是向量的加减 
//拿一个数组存自己与父亲之间的关系
//模拟一下关系的传递的途径与推导结果,可以用相加与取余来构造
//0表示同类,1表示吃父亲,2表示父亲吃自己 

#include<bits/stdc++.h>

using namespace std;

const int maxn = 5e4 + 5;

int n,k;
int father[maxn << 2],d[maxn<<2];

void readdata(){
	read(n);read(k); 
}

int find(int x){
	if(father[x] == x) return x;
	else {
		int root = find(father[x]);
		d[x] = (d[x]+d[father[x]])%3;
		father[x] = root;
		return root;
	}
}

void merge(int x,int y,int opt){
	int fx = find(x),fy = find(y);
	father[fx] = fy;
	d[fx] = (opt+d[y]-d[x]+3)%3; 
}

void work(){
	int ans = 0;
	for(int i = 1;i <= n*3; ++ i) father[i] = i;
	while(k --){
		int t,x,y;
		read(t);read(x);read(y);
		if(x > n || y > n) {
			ans++;
			continue;
		}
		if(t == 1){
			int fx = find(x),fy = find(y);
			if(fx == fy){
				if(d[x]!=d[y]) {
					ans++;
					continue;
				}
			}
			merge(x,y,0);
		} else {
			int fx = find(x),fy = find(y);
			if(fx == fy){
				if((d[x]+(3-d[y]))%3 != 1){
					ans++;
					continue;
				}
			}
			merge(x,y,1);
		}
	}
	put(ans);
}

int main(){
//	file();
	readdata();
	work();
	return 0;
}

扩展域

/********************
User:Mandy
Language:c++
Problem: AcWing 240
Algorithm:
********************/
#include<bits/stdc++.h>

using namespace std;

const int maxn = 5e4 + 5;

int n,k;
int father[maxn << 2];

void readdata(){
	read(n);read(k); 
}

int find(int x){
	return father[x] == x ? x : father[x] = find(father[x]);
}

void merge(int x,int y){
	father[find(x)] = find(y);
}

void work(){
	int ans = 0;
	for(int i = 1;i <= n*3; ++ i) father[i] = i;
	while(k --){
		int d,x,y;
		read(d);read(x);read(y);
		if(x > n || y > n) {
			ans++;
			continue;
		}
		if(d == 1){
			if(find(x) == find(y+n) || find(y) == find(x + n)){
				ans++;
				continue;
			}
			merge(x,y);	merge(x+n,y+n);	merge(x+n+n,y+n+n);
		} else {
			if(find(x) == find(y)||find(x+n) == find(y)){
				ans++;
				continue;
			}
			merge(x,y+n);merge(x+n,y+n+n);merge(x+n+n,y);
		}
	}
	put(ans);
}

int main(){
//	file();
	readdata();
	work();
	return 0;
}

树链剖分

/*********************
User:Mandy
Language:c++
Problem:civilization 
*********************/

#include<bits/stdc++.h>
#define lson l,mid,k<<1
#define rson mid+1,r,k<<1|1

using namespace std;

const int maxn = 1e5 + 5;

int n,m,size,first[maxn],tot,root;
int son[maxn],top[maxn],dep[maxn],cnt[maxn];
int father[maxn],seg[maxn],val[maxn],a[maxn];
long long sum[maxn<<2],lazy[maxn<<2],ans;

struct Edge{
	int v,nt;
}edge[maxn];

void eadd(int u,int v){
	edge[++size].v = v;
	edge[size].nt = first[u];
	first[u] = size;
}

void readdata(){
	read(n);
	for(int i = 1;i <= n; ++ i) read(a[i]);
	for(int i = 2;i <= n; ++ i) read(father[i]),eadd(father[i],i);
	read(m);
}

void dfs1(int u,int d){
	dep[u] = d;cnt[u] = 1;
	int mcnt = 0;
	for(int i = first[u];i;i = edge[i].nt){
		int v = edge[i].v;
		dfs1(v,d+1);
		cnt[u] += cnt[v];
		if(cnt[v]>mcnt){
			mcnt = cnt[v];
			son[u] = v;
		}
	}
}

void dfs2(int u,int tp){
	top[u] = tp;
	seg[u] = ++tot;
	val[tot] = a[u];
	if(!son[u]) return;
	dfs2(son[u],tp);
	for(int i = first[u];i;i = edge[i].nt){
		int v = edge[i].v;
		if(v == son[u]) continue;
		dfs2(v,v);
	}
}

void pushup(int k){
	sum[k] = sum[k<<1]+sum[k<<1|1];
}

void pushdown(int l,int r,int k){
	if(!lazy[k]) return;
	int ls = k<<1,rs = k<<1|1;
	int mid = (l+r)>>1;
	lazy[ls] += lazy[k];lazy[rs] += lazy[k];
	sum[ls] += lazy[k] * (mid-l+1);
	sum[rs] += lazy[k] * (r - mid);
	lazy[k] = 0;
}

void buildtree(int l,int r,int k){
	if(l == r){
		sum[k] = (long long)val[l];
		return;
	}
	int mid = (l + r) >> 1;
	buildtree(lson);
	buildtree(rson);
	pushup(k);
}

void query(int l,int r,int k,int x,int y){
	if(x <= l && r <= y) {ans += sum[k];return;}
	int mid = (l + r) >> 1;
	pushdown(l,r,k);
	if(x <= mid) query(lson,x,y);
	if(y > mid) query(rson,x,y);
	pushup(k);
}

void modify(int l,int r,int k,int x,int y){
	if(x <= l && r <= y) {sum[k] += ans * (r-l+1);lazy[k] += ans;return;}
	int mid = (l + r)>>1;
	pushdown(l,r,k);
	if(x <= mid) modify(lson,x,y);
	if(y > mid) modify(rson,x,y);
	pushup(k);
}

void add(int x,int y){
	while(top[x] != top[y]){
		if(dep[top[x]] < dep[top[y]]) swap(x,y);
		modify(1,n,1,seg[top[x]],seg[x]);
		x = father[top[x]];
	}
	if(dep[x]>dep[y]) swap(x,y);
	modify(1,n,1,seg[x],seg[y]);
}

void ask(int x,int y){
	while(top[x] != top[y]){
		if(dep[top[x]] < dep[top[y]]) swap(x,y);
		query(1,n,1,seg[top[x]],seg[x]);
		x = father[top[x]];
	}
	if(dep[x]>dep[y]) swap(x,y);
	query(1,n,1,seg[x],seg[y]);	
}

int find(int x,int y){
	while(top[x] != top[y]){
		if(father[top[y]] == x) return top[y];
		y = father[top[y]];
	}
	return son[x];
}

void add_subtree(int u){
	if(u == root) {modify(1,n,1,1,n);return;}
	if(seg[u]<=seg[root]&&seg[root]<=seg[u]+cnt[u]-1){
		int ch = find(u,root);
		modify(1,n,1,1,n);
		ans = -ans;
		modify(1,n,1,seg[ch],seg[ch]+cnt[ch]-1);
	} else modify(1,n,1,seg[u],seg[u]+cnt[u]-1);
}

void ask_subtree(int u){
	if(u == root) {ans = sum[1];return;}
	if(seg[u]<=seg[root]&&seg[root]<=seg[u]+cnt[u]-1){
		int ch = find(u,root);
		query(1,n,1,seg[ch],seg[ch]+cnt[ch]-1);
		ans = sum[1]-ans;
	}else query(1,n,1,seg[u],seg[u]+cnt[u]-1);
}

void work(){
	dfs1(1,1);
	dfs2(1,1);
	buildtree(1,n,1);
	while(m--){
		int opt,u,v;read(opt);
		switch(opt){
			case 1:{read(u);root = u;break;}
			case 2:{read(u);read(v);read(ans);add(u,v);break;}
			case 3:{read(u);read(ans);add_subtree(u);break;}
			case 4:{ans = 0;read(u);read(v);ask(u,v);put(ans);putchar('\n');break;}
			case 5:{ans = 0;read(u);ask_subtree(u);put(ans);putchar('\n');break;}
		}
	}
}

int main(){
//	file();
	readdata();
	work();
	return 0;
}

树状数组

O(n)初始化

read(n);read(m);
	for(int i = 1;i <= n; ++ i) read(a[i]);
	for(int i = n;i >= 1; -- i) delta[i] = a[i]-a[i-1];
	for(int i = 1;i <= n; ++ i){
		for(int j = i-1;j > i - lowbit(i);j -= lowbit(j))//注意> 
			delta[i]+=delta[j];
	} 
/************************
User:Mandy.H.Y
Language:c++
Problem:loj130 Binary Index Tree 1
Algorithm:Binary Index Tree
Date:2019.7.10
Scores:100
************************/
//单点修改,区间查询
//c[i]表示从第i个元素向前数lowbit(i)个元素,这一段的和
#include<bits/stdc++.h>

using namespace std;

const int maxn=1e6+5;

int n,q;
long long sum[maxn]; 

int lowbit(int x){
	return x & (-x);
}

void modify(int pos,int val){//i的父亲节点是i+lowbit(i) 
	for(int i=pos;i<=n;i+=lowbit(i)) sum[i]+=(long long)val;
}

void readdata(){
	read(n);read(q);
	for(int i=1;i<=n;++i){
		int x;read(x);
		modify(i,x);
	}
}

long long query(int l,int r){
	long long suml=0,sumr=0;
	for(int i=r;i;i-=lowbit(i)) sumr+=(long long)sum[i];
	for(int i=l-1;i;i-=lowbit(i)) suml+=(long long)sum[i];//注意long long 
	return sumr-suml;
}

void work(){
	while(q--){
		int opt;
		read(opt);
		if(opt==1){
			int pos,val;read(pos);read(val);
			modify(pos,val);
		}else{
			int l,r;
			read(l);read(r);
			put(query(l,r));putchar('\n');
		}
	}
}

int main(){
//	file();
	readdata();
	work();
	return 0;
}
/********************
User:Mandy.H.Y
Language:c++
Problem:loj131 Binary Index Tree 2
Algorithm:Binary Index Tree 2
Date:2019.7.10
Scores:
********************/
//区间修改,单点查询
//差分 
//delta[i]=a[i]-a[i-1](a为原数组) 
//把delta[i]整合为树状数组
//则delta[i]表示从第i个元素向前数lowbit(i)个元素,这一段的和 
#include<bits/stdc++.h>

using namespace std;

const int maxn=1e6+5;

int n,q;
long long delta[maxn];
int lowbit(int x){
	return x & (-x);
} 

void modify(int l,int r,int val){
	for(int i=r+1;i<=n;i+=lowbit(i)) delta[i]-=(long long)val;
	for(int i=l;i<=n;i+=lowbit(i)) delta[i]+=(long long)val;
}

long long query(int pos){
	long long sum=0;
	for(int i=pos;i;i-=lowbit(i)) sum+=delta[i];
	return sum;
}

void readdata(){
	read(n);read(q);
	int x;
	for(int i=1;i<=n;++i){
		read(x);
		modify(i,i,x);//这里直接加值,相当于把[i,i]这个区间所有值加上x 
	}
}

void work(){
	while(q--){
		int opt;read(opt);
		if(opt==1){
			int l,r,x;read(l);read(r);read(x);
			modify(l,r,x); 
		}else{
			int pos;read(pos);
			put(query(pos));putchar('\n');
		}
	}
}

int main(){
//	file();
	readdata();
	work();
	return 0;
}

//第二种方法 
/*
User:Mandy.H.Y
Language:c++
Problem:
*/

/*
//c[i]表示从第i个元素向前数lowbit(i)个元素,这一段的和
#include<bits/stdc++.h>

#define Max(x,y) (x)>(y)?(x):(y)
#define Min(x,y) (x)<(y)?(x):(y)
#define mem(A) memset((A),0,sizeof(A))

using namespace std;

const int maxn=1e6+5;

int n,q;
long long sum[maxn];

int lowbit(int x)
{
	return x&(-x);
}

void modify(int k,int x)
{
	for(int i=k;i<=n;i+=lowbit(i))
	{
		sum[i]+=(long long)x;
	}
}

void query(int r)
{
	long long sum1=0;
	for(int i=r;i>0;i-=lowbit(i)) sum1+=sum[i];
	printf("%lld\n",sum1);
}

void readdata()
{
	read(n);read(q);
	int pre=0;
	for(int i=1;i<=n;++i) 
	{
		int x;
		read(x);
		modify(i,x-pre);
		pre=x;
	}
	
}

void work()
{
	for(int i=1;i<=q;++i)
	{
		int judge,j,x,k;
		read(judge);
		
		if(judge==1)
		{
			read(j); read(k); read(x);
			modify(j,x);
			modify(k+1,-x);
		}
		else
		{
			read(x);
			query(x);
		}
	}
}

int main()
{
//	docu();
	readdata(); 
	work();
	return 0;
}

*/
/*************************
User:Mandy.H.Y
Language:c++
Problem:loj132 Binary Index Tree 3
Algorithm:
Date:2019.7.10
Scores: 
*************************/
//区间修改,区间查询

//设d[i]=a[i]-a[i-1];
//则sum[i]=d[j]*(i-j+1)(j= 1 to i)
//sum[i]=d[j]*(i+1)-d[j]*j (j= 1 to i)
//把d整合为树状数组,修改时向父节点推 

#include<bits/stdc++.h>

using namespace std;

const int maxn=1e6+5;

int n,q;
long long sum[maxn],delta1[maxn],delta2[maxn];

void readdata(){
	read(n);read(q);
	for(int i=1;i<=n;++i){
		int x;read(x);
		sum[i]=sum[i-1]+x;//事先求出sum,delta 中只存改变量 
	}
}

int lowbit(int x){
	return x&(-x);
}

void add(int pos,int val){
	long long mval=(long long)val*(long long)pos;
	for(int i=pos;i<=n;i+=lowbit(i)){
		delta1[i]+=val;
		delta2[i]+=mval;
	}//向上
}

long long query(int pos){
	long long sum1=0,sum2=0;
	for(int i=pos;i;i-=lowbit(i)){
		sum1+=delta1[i];
		sum2+=delta2[i];
	}
	return sum[pos]+sum1*(pos+1)-sum2; 
}

void work(){
	while(q--){
		int opt,l,r,x;read(opt);
		if(opt==1){
			read(l);read(r);read(x);
			add(l,x);add(r+1,-x);
		}else{
			read(l);read(r);
			put(query(r)-query(l-1));
			putchar('\n');
		}
	}
}

int main(){
//	file();
	readdata();
	work();
	return 0;
}
/************************
User:Mandy.H.Y
Language:c++
Problem:
Algorithm:
Date:
Score:
************************/

//单点修改,区间查询 

#include<bits/stdc++.h>

using namespace std;

const int maxn = (1 << 12) + 5;

int n,m;
long long a[maxn][maxn];

void readdata(){
	read(n);read(m);
}

int lowbit(int x){
	return x & (-x);
}

void modify(int x,int y,long long val){
	for(int i = x;i <= n;i += lowbit(i))
			a[i][j] += val;
}

long long query(int x,int y){
	long long sum=0;
	for(int i = x;i;i -= lowbit(i))
		for(int j = y;j;j -= lowbit(j))
			sum += a[i][j];
	return sum;
}

void work(){
	int opt,a,b,c,d;
	long long delta;
	while(~scanf("%d",&opt)){
		if(opt == 1){
			read(a);read(b);read(delta);
			modify(a,b,delta);		
		}else if(opt == 2){
			read(a);read(b);read(c);read(d);
			long long ans = query(c,d) - query(c,b - 1)
							- query(a - 1,d) + query(a - 1,b - 1);
			put(ans);putchar('\n');
		}
	}
}

int main(){
	file();
	readdata();
	work();
	return 0;
}

逆序对

/************************
User:Mandy.H.Y
Language:c++
Problem:luogu1908 Reverse order pair
Algorithm:归并排序
Date:2019.7.11
Scores: 
************************/

#include<bits/stdc++.h>

using namespace std;

const int maxn=5e5+5;

long long n,ans=0;//记得开long long 
int a[maxn];
int temp[maxn];

void readdata(){
	read(n);
	for(int i=1;i<=n;++i) read(a[i]);
}

void merge(int l,int r){
	if(l>=r) return;
	
	int mid=(l+r)>>1;
	int i=l,j=mid+1,k=l;
	
	merge(l,mid);merge(mid+1,r);
	
	while(i<=mid && j<=r){
		if(a[j]>=a[i]){
			temp[k++]=a[i++];
		}else{
			temp[k++]=a[j++];
			ans+=(long long)mid-i+1;//前面比a[j]大的数的个数 
		}
	}
	
	while(i<=mid) temp[k++]=a[i++];//这里不必再加 
	while(j<=r) temp[k++]=a[j++];
	
	for(int i=l;i<=r;++i) a[i]=temp[i];
}

void work(){
	merge(1,n); 
	put(ans);
	/*
	puts("");
	for(int i=1;i<=n;++i){
		printf("%d ",a[i]);
	}
	*/
}

int main(){
//	file();
	readdata();
	work();
	return 0;
}
/*************************
User:Mandy.H.Y
Language:c++
Problem:luogu1908 Reverse order pair
Algorithm:树状数组
Date:2019.7.11
Scores: 
*************************/
//用结构体排序,离散排名 
#include<bits/stdc++.h>
using namespace std;

const int maxn=5e5+5;

struct node{
	int id,v;
}a[maxn];

int n,rank[maxn];
long long ans=0,tree[maxn];

int lowbit(int x){
	return x & (-x);
}

void add(int pos){
	for(int i=pos;i<=n;i+=lowbit(i)) ++tree[i];
}

long long query(int pos){
	long long sum=0;
	for(int i=pos;i;i-=lowbit(i)) sum+=tree[i];
	return sum;
}

void readdata(){
	read(n);
	for(int i=1;i<=n;++i) read(a[i].v),a[i].id=i;
}

bool cmp(const node &x,const node &y){
	if(x.v==y.v) return x.id<y.id;
	else return x.v<y.v ;
}

void work(){
	sort(a+1,a+n+1,cmp);
	
	for(int i=1;i<=n;++i) rank[a[i].id]=i;
	
	for(int i=1;i<=n;++i){
		add(rank[i]);
		ans+=i-query(rank[i]);
	}
	
	put(ans);
}

int main(){
//	file();
	readdata();
	work();
	return 0;
}

线段树

推荐阅读

  1. 有趣的线段树模板合集

区间加,区间和

题目:luogu3372

/*
ID:胡芸 Mandy
language:c++
problem:luogu 3372
*/
#include<bits/stdc++.h>

#define N 100003
#define M 100003
#define Max(x,y) (x)>(y)?(X):(y)
#define Min(x,y) (x)<(y)?(x):(y)
#define up(i,l,r) for(int i=l;i<=r;++i)
#define down(i,l,r) for(int i=r;i>=l;--i)

using namespace std;

long long n,m;
long long sum[N<<2],change,add[N<<2];

void readdata()
{
	n=read();
	m=read();
} 

void build(long long k,int l,int r)
{
	if(l==r)
	{
		sum[k]=read();
		return;
	}
	int mid=(l+r)>>1;
	int lk=k<<1;
	int rk=lk+1;
	build(lk,l,mid);
	build(rk,mid+1,r);
	sum[k]=sum[lk]+sum[rk];
}

void push_down(int k,int l,int r)
{
	if(!add[k]) return;
	int mid=(l+r)>>1;
	int lk=k<<1;
	int rk=lk|1;
	add[lk]+=add[k];
	add[rk]+=add[k];
	sum[lk]+=add[k]*(mid-l+1);
	sum[rk]+=add[k]*(r-mid);
	add[k]=0;
}

void modify(int k,int l,int r,int x,int y)
{
	if(r<x||l>y) return;
	if(x<=l&&y>=r)
	{
		add[k]+=change;
		sum[k]+=change*(r-l+1);
		return;
	}
	else
	{
		push_down(k,l,r);
		int mid=(l+r)>>1;
		modify(k<<1,l,mid,x,y);
		modify((k<<1)+1,mid+1,r,x,y);
		sum[k]=sum[k<<1]+sum[(k<<1)+1];
	}
}

long long ask(int k,int l,int r,int x,int y)
{
	if(r<x||l>y) return 0;
	if(x<=l&&y>=r) return sum[k];
	else
	{
		push_down(k,l,r);
		int mid=(l+r)>>1;
		return ask(k<<1,l,mid,x,y)+ask((k<<1)+1,mid+1,r,x,y);//注意左移右移 
	}
}

void work()
{
	build(1,1,n);
	up(i,1,m)
	{
		int j=read(),x=read(),y=read();
		if(y<x) swap(x,y);
		if(j==1)
		{
			change=read();
			modify(1,1,n,x,y);
		}
		else
		{
			put(ask(1,1,n,x,y));
			putchar('\n');
		}
	}
}

int main()
{
	//docu();
	readdata();
	work();
	return 0;
} 

区间加,区间乘,区间和

luogu3373

双倍经验

/*
ID:胡芸 Mandy
language:c++
problem:luogu 3373
*/
#include<bits/stdc++.h>

#define N 100002
#define M 100002
#define minl -8446744073709551616
#define Max(x,y) (x)>(y)?(x):(y)
#define Min(x,y) (x)<(y)?(x):(y)
#define up(i,l,r) for(int i=l;i<=r;++i)
#define down(i,l,r) for(int i=r;i>=l;--i)

using namespace std;

long long n,m,p,sum[N<<2],change;
long long add[N<<2],mul[N<<2];

inline long long read()
{
	long long x=0; char c=getchar(); bool f=0;
	while(c<'0'||c>'9') {f|=c=='-'; c=getchar();}
	while(c>='0'&&c<='9') {x=(x<<3)+(x<<1)+(c^48); c=getchar();}
	return f?-x:x;
} 

inline void put(long long x)
{
	if(x<0) {putchar('-'); x=-x;}//注意0 与负数 
	if(x==0) {putchar('0'); return;}
	int num=0;char c[21];
	while(x) {c[++num]=(x%10)^48; x/=10;}
	while(num) putchar(c[num--]);
}

void docu()
{
	freopen("3373.in","r",stdin);
//	freopen("3373.out","w",stdout); 
} 

void build(int k,int l,int r)
{
	mul[k]=1;//初始化,输入的mul可能为零 
	if(l==r)
	{
		sum[k]=read();//注意sum[k] 
		return;
	}
	int mid=(l+r)>>1;
	int lk=k<<1;
	int rk=lk|1;
	build(lk,l,mid);
	build(rk,mid+1,r);
	sum[k]=sum[lk]+sum[rk];
}

void readdata()
{
	n=read();
	m=read();
	p=read();
	build(1,1,n);
}

void push_down(int k,int l,int r)//先乘后加 
{
	int mid=(l+r)>>1;
    int lk=k<<1;
	int rk=lk|1;
	    sum[lk]=sum[lk]*mul[k]%p;
	    sum[rk]=sum[rk]*mul[k]%p;//赋值 
	    mul[lk]=mul[lk]*mul[k]%p;
	    mul[rk]=mul[rk]*mul[k]%p;//传递 
	    
		sum[lk]=(sum[lk]+add[k]*(mid-l+1))%p;
	    sum[rk]=(sum[rk]+add[k]*(r-mid))%p;//赋值 
	    add[lk]=(add[lk]*mul[k]+add[k])%p;//注意要乘以mul 
	    add[rk]=(add[rk]*mul[k]+add[k])%p;//传递 
		mul[k]=1;//归一防重 
	    add[k]=0;//归零防重 //注意位置 
	//sum[k]=sum[lk]+sum[rk];此处不需更新 
}

long long ask(int k,int l,int r,int x,int y)
{
	if(l>=x&&r<=y) return sum[k];
	else
	{
		int mid=(l+r)>>1;
		long long ans1=0,ans2=0;
		push_down(k,l,r); //注意 
		if(x<=mid) ans1=ask(k<<1,l,mid,x,y);//注意左右移 
		if(y>mid) ans2=ask((k<<1)|1,mid+1,r,x,y);
		return ans1+ans2;
	}
}

void multiply(int k,int l,int r,int x,int y)
{
	if(r<x||l>y) return;
	if(l>=x&&r<=y)
	{
		add[k]=add[k]*change%p;
		sum[k]=sum[k]*change%p;//add[k]也要乘 
		mul[k]=mul[k]*change%p;
		return;
	}
	else
	{
		int mid=(l+r)>>1;
		push_down(k,l,r);//注意别漏 
		if(x<=mid) multiply(k<<1,l,mid,x,y);
		if(mid<y) multiply((k<<1)|1,mid+1,r,x,y);
		sum[k]=(sum[k<<1]+sum[(k<<1)|1])%p; //注意更新 
	}
	
}

void plus1(int k,int l,int r,int x,int y)
{
	if(r<x||l>y) return;
	if(l>=x&&r<=y)
	{
		add[k]=(add[k]+change)%p;//add数组不乘区间长 
		sum[k]=(sum[k]+change*(r-l+1))%p;//加数要乘区间长,乘数不用 
		return;
	}
	else
	{
		int mid=(l+r)>>1;
		push_down(k,l,r);//注意 
		if(x<=mid) plus1(k<<1,l,mid,x,y);
		if(mid<y) plus1((k<<1)|1,mid+1,r,x,y);
		sum[k]=(sum[k<<1]+sum[(k<<1)|1])%p; //注意更新 
	}
	
}

void work()
{
	up(i,1,m)
	{
		long long judge=read(),x=read(),y=read();
		if(judge==1)
		{
			change=read();
			multiply(1,1,n,x,y);
		}
		else
		{
			if(judge==2)
		    {
			    change=read();
			    plus1(1,1,n,x,y);
			    
		    }
		    else
		    {
		    	put(ask(1,1,n,x,y)%p);
		    	putchar('\n');
			}
		}
	}
}

int main()
{
//	docu();
	readdata();
	work();
	return 0;
}
/***********************
User:Mandy.H.Y
Language:c++
Problem:luogu2023
Algorithm: 
***********************/

#include<bits/stdc++.h>
#define Max(x,y) ((x) > (y) ? (x) : (y))
#define Min(x,y) ((x) < (y) ? (x) : (y))
#define lson l,mid,k << 1
#define rson mid + 1,r,k << 1 | 1

using namespace std;

const int maxn = 1e5 + 5;

long long n,p,c,m;
long long tree[maxn << 2],lazy1[maxn << 2],lazy2[maxn << 2];

void pushup(int k){
	tree[k] = (tree[k << 1] + tree[k << 1 | 1]) % p;
}

void buildtree(int l,int r,int k){
	lazy2[k] = 1;
	//初始化 
	if(l == r){
		read(tree[k]);
		return ;
	}
	
	int mid = (l + r) >> 1;
	buildtree(lson);
	buildtree(rson);
	pushup(k);
}

void readdata(){
	read(n);read(p);
	buildtree(1,n,1);
	read(m);
}

void pushdown(int l,int r,int k){
	int mid = (l + r) >> 1;
	int ls = k << 1;
	int rs = k << 1 | 1;
	int ll = (mid - l + 1);
	int rl = (r - mid);
	lazy1[ls] = (lazy1[ls] * lazy2[k] + lazy1[k]) % p;
	lazy1[rs] = (lazy1[rs] * lazy2[k] + lazy1[k]) % p;
	lazy2[ls] = (lazy2[ls] * lazy2[k]) % p;
	lazy2[rs] = (lazy2[rs] * lazy2[k]) % p;
	tree[ls] = (tree[ls] * lazy2[k] + lazy1[k] * ll) % p;
	tree[rs] = (tree[rs] * lazy2[k] + lazy1[k] * rl) % p;
	lazy1[k] = 0;lazy2[k] = 1;
}

void add(int l,int r,int k,int x,int y){
	if(x <= l && r <= y){
		lazy1[k] = (lazy1[k] + c) % p;
		tree[k] = (tree[k] + c * (r - l + 1)) % p;
		return;
	}
	pushdown(l,r,k);
	int mid = (l + r) >> 1;
	if(x <= mid) add(lson,x,y);
	if(y > mid) add(rson,x,y);
	pushup(k);
}

void multiply(int l,int r,int k,int x,int y){
	if(x <= l && r <= y){
		lazy1[k] = (lazy1[k] * c) % p;
		lazy2[k] = (lazy2[k] * c) % p;
		tree[k] = (tree[k] * c) % p;
		return;
	}
	pushdown(l,r,k);
	int mid = (l + r) >> 1;
	if(x <= mid) multiply(lson,x,y);
	if(y > mid) multiply(rson,x,y);
	pushup(k);
}

long long query(int l,int r,int k,int x,int y){
	if(x <= l && r <= y){	
		return tree[k];
	}
	pushdown(l,r,k);
	int mid = (l + r) >> 1;
	long long ans = 0;
	if(x <= mid) ans += query(lson,x,y);
	if(y > mid) ans += query(rson,x,y);
	pushup(k);
	return ans % p;
}

void work(){
	while(m -- ){
		int opt,t,g;
		read(opt);
		switch(opt){
			case 1:{
				read(t),read(g),read(c);
				multiply(1,n,1,t,g);
				break;
			}
			case 2:{
				read(t),read(g),read(c);
				add(1,n,1,t,g);
				break;
			}
			default :{
				read(t);read(g);
				long long ans = query(1,n,1,t,g);
				put(ans);putchar('\n');
				break;
			}
		}
	}
}

int main(){
//	file();
	readdata();
	work();
	return 0;
}

区间开方

luogu 4145

/***********************
User:Mandy.H.Y
Language:c++
Problem:luogu4115 flower
Algorithm:
Date:2019.7.16
Algorithm:
***********************/

//一个小小的优化:1开方还是1,0开方还是0 
//当一个区间的最大值都为1 或0 
//这个区间开方就不会变 
//由于数字都小于等于1e12,每个数至多开方开六次就会变为1 
#include<bits/stdc++.h>

using namespace std;

const int maxn = 1e5+5;

long long n,m;
long long tree[maxn<<2],ans; 
long long Max[maxn<<2];
//虽然是区间修改,但开方不能区间操作,lazy就算了吧…… 

void push_up(int k){
	tree[k]=tree[k<<1]+tree[k<<1|1];
	Max[k]=max(Max[k<<1],Max[k<<1|1]);
}

void buildtree(int l,int r,int k){
	if(l==r){
		read(tree[k]);
		Max[k]=tree[k];
		return;
	}
	int mid=(l+r)>>1;
	buildtree(l,mid,k<<1);
	buildtree(mid+1,r,k<<1|1);
	push_up(k);
}

void readdata(){
	read(n);
	buildtree(1,n,1);
	read(m);
}

void modify(int l,int r,int k,int x,int y){
	if(l==r){
		Max[k]=floor(sqrt(Max[k]));
		tree[k]=Max[k];
		return;
	}
	int mid=(l+r)>>1;
	if(x<=mid && Max[k<<1]>1) modify(l,mid,k<<1,x,y);
	if(y>mid && Max[k<<1|1]>1) modify(mid+1,r,k<<1|1,x,y);
	push_up(k);
}

void query(int l,int r,int k,int x,int y){
	if(x<=l&& y>=r){
		ans+=tree[k];
		return;
	}
	int mid=(l+r)>>1;
	if(x<=mid) query(l,mid,k<<1,x,y);
	if(y>mid) query(mid+1,r,k<<1|1,x,y);	
}

void work(){
	while(m--){
		int k,l,r;
		read(k);read(l);read(r);
		if(l>r) swap(l,r);
		if(!k) modify(1,n,1,l,r);
		else {
			ans=0;
			query(1,n,1,l,r);
			put(ans);
			putchar('\n');
		}	
	}
}

int main(){
//	file();
	readdata();
	work();
	return 0;
}

区间最值,区间加,区间整除

loj 6029

/*****************************
User:Mandy.H.Y
Language:c++
Problem:market
*****************************/
//
#include<bits/stdc++.h>
#define lson l,mid,k << 1
#define rson mid + 1,r,k << 1 | 1
#define Max(x,y) ((x) > (y) ? (x) : (y))
#define Min(x,y) ((x) < (y) ? (x) : (y))

using namespace std;

const int maxn = 1e5 + 5;

int n,q;
long long sum[maxn << 2];
int mi[maxn << 2],ma[maxn << 2],lazy[maxn << 2];
int L,R,C,D;

void pushup(int k){
	int ls = k << 1;
	int rs = k << 1 | 1;
	sum[k] = sum[ls] + sum[rs];
	mi[k] = Min(mi[ls],mi[rs]);
	ma[k] = Max(ma[ls],ma[rs]);
} 

void buildtree(int l,int r,int k){
	if(l == r){
		read(mi[k]);
		sum[k] = ma[k] = mi[k];
		return ;
	}
	int mid = (l + r) >> 1;
	buildtree(lson);
	buildtree(rson);
	pushup(k);
}

void readdata(){
	read(n);read(q);
	buildtree(1,n,1);
}

void pushdown(int l,int r,int k){
	if(!lazy[k]) return;
	int ls = k << 1;
	int rs = ls | 1;
	int mid = (l + r) >> 1;
	sum[ls] += (long long)lazy[k] * (mid - l + 1);
	sum[rs] += (long long)lazy[k] * (r - mid);
	mi[ls] += lazy[k];ma[ls] += lazy[k]; 
	mi[rs] += lazy[k];ma[rs] += lazy[k]; 
	lazy[ls] += lazy[k];
	lazy[rs] += lazy[k];
	lazy[k] = 0;
}

void add(int l,int r,int k){
	if(L <= l && r <= R){
		sum[k] += (long long)C * (r - l + 1);
		mi[k] += C;
		ma[k] += C;
		lazy[k] += C;
		return;
	}
	pushdown(l,r,k);
	int mid =  (l + r) >> 1;
	if(L <= mid) add(lson);
	if(R > mid) add(rson);
	pushup(k);
}

void div(int l,int r,int k){//如果区间最大值与最小值的下降的值都一样,那么区间下降的值一样 
	if(L <= l && r <= R){
		int tmp1 = ma[k] - (int)floor((double)ma[k]/(double)D);
		int tmp2 = mi[k] - (int)floor((double)mi[k]/(double)D);
		if(tmp1 == tmp2){
			sum[k] -= (long long)tmp1 * (r - l + 1);
			mi[k] -= tmp1;
			ma[k] -= tmp1;
			lazy[k] -= tmp1;
			return;
		}
	}
	pushdown(l,r,k);
	int mid =  (l + r) >> 1;
	if(L <= mid) div(lson);
	if(R > mid) div(rson);
	pushup(k);	
}

long long get_sum(int l,int r,int k){
	if(L <= l && r <= R) return sum[k];
	pushdown(l,r,k);
	int mid =  (l + r) >> 1;
	long long ans = 0;
	if(L <= mid) ans += get_sum(lson);
	if(R > mid) ans += get_sum(rson);
	pushup(k);
	return ans;
}

int get_min(int l,int r,int k){
	if(L <= l && r <= R) return mi[k];
	pushdown(l,r,k);
	int mid =  (l + r) >> 1;
	int ans1 = 2e9 + 5;
	int ans2 = 2e9 + 5;
	if(L <= mid) ans1 = get_min(lson);
	if(R > mid) ans2 = get_min(rson);
	pushup(k);
	return Min(ans1,ans2);
}

void work(){
	while(q --){
		int opt;
		read(opt);
		switch(opt){
			case 1:{
				read(L);read(R);read(C);
				L++,R++;//注意本题给出的标号从0开始 
				add(1,n,1);
				break;
			}
			case 2:{
				read(L);read(R);read(D);
				L++,R++;
				div(1,n,1);
				break;
			}
			case 3:{
				read(L);read(R);L++,R++;
				int ans = get_min(1,n,1);
				put(ans);puts("");
				break;
			}
			case 4:{
				read(L);read(R);
				L++,R++;
				long long ans = get_sum(1,n,1);
				put(ans);puts("");
				break;
			}
		}
	}
}

int main(){
//	file();
	readdata();
	work(); 
	return 0;
}

区间最大子段和

/*********************
User:Mandy
Langauge:c++
Problem:luogu
Algorithm:
*********************/
#include<bits/stdc++.h>
#define lson l,mid,k<<1
#define rson mid+1,r,k<<1|1

using namespace std;

const int maxn = 5e5 + 5;
const int maxm = 1e5 + 5;
const long long INF = 4e17;

int n,m;

struct ANS{
	long long l,r,sum,m;
}tree[maxn << 2];

void pushup(int k){
	tree[k].sum = tree[k << 1].sum + tree[k << 1 | 1].sum;
	tree[k].l = max(tree[k<<1].l,tree[k<<1].sum + tree[k<<1|1].l);//	tree[k].mÊÇÇø¼ä×î´óµÄ×Ӷκͣ¬´óÓÚµÈÓÚtree[k].lÓëtree[k].r 
	tree[k].m = max(tree[k<<1].m,max(tree[k<<1|1].m,tree[k<<1].r+tree[k<<1|1].l));
	tree[k].r = max(tree[k<<1|1].r,tree[k<<1|1].sum + tree[k<<1].r);
} 

void buildtree(int l,int r,int k){
	if(l == r){
		read(tree[k].l);tree[k].sum = tree[k].l;
		tree[k].m = tree[k].r = tree[k].l;
		return;
	}
	int mid = (l + r) >> 1;
	buildtree(lson);buildtree(rson);
	pushup(k);
}

void readdata(){
	read(n);read(m);
	buildtree(1,n,1);
}

ANS query(int l,int r,int k,int x,int y){
	if(x <= l && r <= y) return tree[k];
	int mid = (l + r) >> 1;ANS ans1 = (ANS){-INF,-INF,-INF,-INF},ans2 = (ANS){-INF,-INF,-INF,-INF},ans;
	if(x <= mid) ans1 = query(lson,x,y);
	if(y > mid) ans2 = query(rson,x,y);
	if(ans1.m == -4e17) ans = ans2;
	else if(ans2.m == -4e17) ans = ans1;
	else {
		ans.sum = ans1.sum + ans2.sum;
		ans.l = max(ans1.l,ans1.sum + ans2.l);
		ans.m = max(ans1.m,max(ans2.m,ans1.r+ans2.l));
		ans.r = max(ans2.r,ans2.sum + ans1.r);
	}
	return ans;
}

void modify(int l,int r,int k,int x,int val){
	if(l == r && l == x) {
		tree[k].l = val,tree[k].r = val,tree[k].m = tree[k].sum = val;
		return;
	}
	int mid = (l + r) >> 1;
	if(x <= mid) modify(lson,x,val);
	if(x > mid) modify(rson,x,val);
	pushup(k);
}

void work(){
	while(m -- ){
		int opt;read(opt);
		if(opt == 1){
			int l,r;read(l);read(r);if(l > r) swap(l,r);
			ANS ans = query(1,n,1,l,r);
			put(ans.m);putchar('\n');
		} else {
			int x,y;read(x);read(y);
			modify(1,n,1,x,y);
		}
	}
}

int main(){
	readdata();
	work();
	return 0;
}

区间GCD + 修改

/*****************
User:Mandy
Langauge:c++
Problem:luogu
Algorithm:
*****************/
//差分,单点修改与区间GCD
//线段树 + 树状数组
//不过可以直接线段树区间修改+GCD 
//开long long !!!!!!!!!!!!!
//遇到负数怎么办?gcd(a,b) = gcd(a,-b),注意是差分所以不能改变树里的值 
#include<bits/stdc++.h>
#define lson l,mid,k<<1
#define rson mid+1,r,k<<1|1

using namespace std;

const int maxn = 5e5 + 5;
const long long inf = 4e17;

int n,m;
long long tree[maxn<<2];
long long a[maxn];
long long gcd(long long x,long long y){
	if(x < 0) x = -x;if(y < 0) y = -y;//!!!!!!!!!!!!!!
	if(!y) return x;//!!!!!!
	return x % y ? gcd(y,x % y) : y;
}

void pushup(int k){
	tree[k] = gcd(tree[k << 1],tree[k << 1 | 1]);
}

int lowbit(int x){
	return x & (-x);
}

void buildtree(int l,int r,int k){
	if(l == r){read(a[l]);tree[k] = a[l]-a[l-1];return;}
	int mid = (l + r) >> 1;
	buildtree(lson);buildtree(rson);
	pushup(k);
}

void readdata(){
	read(n);read(m);
	buildtree(1,n,1);
	for(int i = n; i >= 1; -- i) a[i] = a[i] - a[i - 1];
	for(int i = 1;i <= n; ++ i){
		for(int j = i - 1;j > i - lowbit(i);j -= lowbit(j)){
			a[i] += a[j];
		}
	}
}

void add(int pos,long long val){
	for(int i = pos;i <= n;i += lowbit(i)) a[i] += val;
}

long long ask(int pos){
	long long sum = 0;
	for(int i = pos;i; i -= lowbit(i)) sum += a[i];
	return sum;
}

void modify(int l,int r,int k,int x,long long y){
	if(x == l && l == r) {tree[k] += y;return ;}
	int mid = (l + r) >> 1;
	if(x <= mid) modify(lson,x,y);
	if(x > mid) modify(rson,x,y);
	pushup(k);
}

long long query(int l,int r,int k,int x,int y){
	if(x <= l && r <= y) {return abs(tree[k]);}//abs
	int mid = (l + r) >> 1;
	long long ans1 = -1,ans2 = -1,ans;
	if(x <= mid) ans1 = query(lson,x,y);
	if(y > mid) ans2 = query(rson,x,y);
	if(ans1 == -1) ans = ans2;
	else if(ans2 == -1) ans = ans1;
	else ans = gcd(ans1,ans2);
	return abs(ans);//abs
}

void work(){
	while(m -- ){
		char ch = getchar();
		while(ch != 'C' && ch != 'Q') ch = getchar();
		if(ch == 'C'){
			long long l,r,d;read(l);read(r);read(d);
			modify(1,n,1,l,d);
			if(r + 1 <= n) modify(1,n,1,r+1,-d);
			add(l,d);
			if(r + 1 <= n) add(r+1,-d);//注意边界 !!!!!!!!!!!
		} else {
			int l,r;read(l);read(r);
			long long a = ask(l);
			long long b = query(1,n,1,l+1,r);
			put(gcd(a,b));putchar('\n');
		}
	}
}

int main(){
//	freopen("in.txt","r",stdin);
//	freopen("out.txt","w",stdout);
	readdata();
	work();
	return 0;
} 

区间&,区间|,查询区间^

//不拆位 
/********************
User:Mandy
Language:c++
Problem:
********************/
//关于&操作的结果,是把原来的1变成了0,其余位不改变
//也就是说,这个&操作,相当于0的or操作,
//对于change,如果change的这一位是1,那么这一位的答案不影响,如果这一位是0,那么区间所有数的这一位都变成了0 
//|操作恰恰相反,
// 对于change,如果change的这一位是0,那么这一位的答案不影响,如果这一位是1,那么区间所有数的这一位都变成了1
//接下来就是奇偶讨论了
//about lazytag:与区间长度的奇偶性有关,与父亲区间长无关,所以从父亲继承的时候保留原来的的值 
//&操作因为是赋零,0的异或值一定是0所以不分奇偶讨论 
#include<bits/stdc++.h>
#define lson l,mid,k<<1
#define rson mid + 1,r,k<<1|1

using namespace std;

const int maxn = 2e5 + 5;
const int init = (1 << 30)-1;

int n,m,change;
int tree[maxn << 2];
int  lazy[maxn << 2][3];
//lazy[k][0] -> & 
//lazy[k][1] -> | 

void pushup(int k){
	tree[k] = tree[k<<1]^tree[k<<1|1];
}

void buildtree(int l,int r,int k){
	lazy[k][0] = init;//初值!!! 
	if(l == r){
		read(tree[k]);
		return;
	}
	int mid = (l + r) >> 1;
	buildtree(lson);
	buildtree(rson);
	pushup(k);
}

void readdata(){
	read(n);read(m);
	buildtree(1,n,1);
}

void pushdown(int l,int r,int k){
	int mid = (l+r)>>1;
	int ls = k<<1;
	int rs = k<<1|1;
	tree[ls] &= lazy[k][0];
	tree[rs] &= lazy[k][0];
	
	lazy[ls][0] &= lazy[k][0];
	lazy[rs][0] &= lazy[k][0];
	lazy[ls][1] &= lazy[k][0];
	lazy[rs][1] &= lazy[k][0];
	lazy[ls][1] |= lazy[k][1];
	lazy[ls][0] |= lazy[k][1];
	lazy[rs][1] |= lazy[k][1];
	lazy[rs][0] |= lazy[k][1];
	//about lazytag:与区间长度的奇偶性有关,与父亲区间长无关,所以从父亲继承的时候保留原来的的值
	if((mid-l+1)&1) tree[ls] |= lazy[k][1];
	else tree[ls] &= (init ^ lazy[k][1]);
	
	if((r - mid) & 1) tree[rs] |= lazy[k][1];	
	else tree[rs] &= (init ^ lazy[k][1]);	
	
	lazy[k][0] = init;
	lazy[k][1] = 0;
}

void And(int l,int r,int k,int x,int y){
	if(x <= l && r <= y){
		tree[k] &= change;
		lazy[k][0] &= change;
		lazy[k][1] &= change;
		//&操作因为是赋零,0的异或值一定是0所以不分奇偶讨论 
		//因为lazytag之间操作会相互影响,所以也要互相标记
		return;
	}
	pushdown(l,r,k);
	int mid = (l + r) >> 1;
	if(x <= mid) And(lson,x,y);
	if(y > mid) And(rson,x,y);
	pushup(k);
}

void Or(int l,int r,int k,int x,int y){
	if(x <= l && r <= y){
		if((r-l+1)&1) tree[k] |= change;
		else tree[k] &= (init ^change);
		
		lazy[k][1] |= change;
		lazy[k][0] |= change;
		return;
	}
	pushdown(l,r,k);
	int mid = (l + r) >> 1;
	if(x <= mid) Or(lson,x,y);
	if(y > mid) Or(rson,x,y);
	pushup(k);
}

int  query(int l,int r,int k,int x,int y){
	if(x <= l && r <= y) return tree[k];
	pushdown(l,r,k);
	int mid = (l + r) >> 1;
	int ans = 0;
	if(x <= mid) ans ^= query(lson,x,y);
	if(y > mid) ans^= query(rson,x,y);	
	return ans;
}

void work(){
	while(m--){
		int opt,k,l,r;		
		read(opt);
		
		switch(opt){//opt possible != 1 or 2 or 3
			case 1:{
				read(l);read(r);
				read(change);
				And(1,n,1,l,r);
				break;
			}
			case 2:{read(l);read(r);
				read(change);
				Or(1,n,1,l,r);
				break;
			}
			case 3:{read(l);read(r);
				int ans = query(1,n,1,l,r);
				put(ans);
				puts("");
				break;
			}
			default:{
				break;
			}
		}
	}
}

int main(){
//	file();
	readdata();
	work();
	return 0;
}

扫描线

Atlantis

#include<bits/stdc++.h>
#define lson l,mid,k<<1
#define rson mid+1,r,k<<1|1

using namespace std;

const int maxn = 105;

int n,tot,cnt,num;
double tmp[maxn<<2],ans;
//因为tmp中存的是坐标 
//这里为了划分区间不重不漏,统一规定tmp[i]表示的是i坐标到i+1坐标的一段区间 
struct Tree{
	int cnt;
	double len;
}tree[maxn<<4];

struct Node{
	double x,y,y2,k;
}node[maxn<<1];//数组范围 
bool cmp(const Node &x,const Node &y){
	return x.x < y.x;
}

void readdata(){
	tot = 0,cnt = 0;num = 0;memset(tree,0,sizeof(tree));
	for(int i = 1;i <= n; ++ i){
		double a,b,c,d;	scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
		node[++num].k = 1,node[num].x = a,node[num].y = b,node[num].y2 = d;
		node[++num].k = -1,node[num].x = c,node[num].y = b,node[num].y2 = d;
		tmp[++tot] = node[num].y;tmp[++tot] = node[num].y2;
	}
	sort(tmp+1,tmp+tot+1);
	cnt = unique(tmp+1,tmp+tot+1)-(tmp+1);
	for(int i = 1;i <= num;i += 2){
		int pos1 = lower_bound(tmp+1,tmp+1+cnt,node[i].y)-tmp;
		int pos2 = lower_bound(tmp+1,tmp+1+cnt,node[i].y2)-tmp;
		node[i].y = node[i+1].y = pos1;node[i].y2 = node[i+1].y2 = pos2;
	}
	sort(node+1,node+num+1,cmp);
}

void pushup(int l,int r,int k){//!!!!!!!!!!!!!!
	if(tree[k].cnt > 0) tree[k].len = tmp[r+1]-tmp[l];
	else tree[k].len = tree[k<<1].len + tree[k<<1|1].len;
}

void modify(int l,int r,int k,int x,int y,int val){
	if(x <= l && r <= y) {
		tree[k].cnt += val;
		pushup(l,r,k);//注意在cnt改变时,要更新len值 
		return;
	}  
	int mid = (l + r) >> 1;
	if(x <= mid) modify(lson,x,y,val);
	if(y > mid) modify(rson,x,y,val);
	pushup(l,r,k);
}

void work(int t){
	node[num+1].x = -1;ans = 0;
	for(int i = 1;i <= num; ++ i){
		modify(1,cnt,1,node[i].y,node[i].y2-1,node[i].k);//注意要-1才能正确表示区间 
		if(node[i+1].x != node[i].x){
			double len = node[i+1].x - node[i].x;//注意double 
			ans += len * (tree[1].len);
		}
	}
	printf("Test case #%d\n",t);
	printf("Total explored area: %.2lf\n\n",ans);
}

int main(){
	read(n);
	int t = 0;
	while(n){
		++t;
		readdata();
		work(t);
		read(n);
	}
	return 0;
}

线段树合并

天天爱跑步

/**********************
User:Mandy
Language:c++
Problem:luogu1600
Algorithm: 
**********************/
//还是,把变转为不变的思想 
#include<bits/stdc++.h>

using namespace std;

const int maxn = 3e5 + 5;

int n,m,first[maxn],size,w[maxn],root[maxn],rab[maxn],tot,cnt_rab,maxl;
int top[maxn],cnt[maxn],dep[maxn],father[maxn],ans[maxn];
struct Edge{int v,nt;}edge[maxn << 1];
struct SegmentTree{int l,r,val[2];}tree[maxn * 60];
/*----------输入输出优化----------*/
//char *mo,*TT,but[(1 << 18) + 2];
//#define getchar() ((TT == mo && (mo = ((TT = but) + fread(but,1,1 << 18,stdin)),TT == mo)) ? -1 : *TT++)
template<class T>inline void read(T &x){
	x = 0;char ch = getchar();bool flag = 0;
	while(!isdigit(ch)) flag |= ch == '-',ch = getchar();
	while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar();
	if(flag) x = -x;
}//读优打错了 
template<class T>void putch(const T x){if(x > 9) putch(x / 10);putchar(x % 10 | 48);}
template<class T>void put(const T x){if(x < 0) putchar('-'),putch(-x);else putch(x);}
/*----------读入数据 & 建图----------*/
void eadd(int u,int v){edge[++size].v = v;edge[size].nt = first[u];first[u] = size;}

void readdata(){
	read(n);read(m);maxl = n*2 + 5;
	for(int i = 1;i < n; ++ i){int u,v;read(u);read(v);eadd(u,v);eadd(v,u);}
	for(int i = 1;i <= n; ++ i) read(w[i]);//n和m傻傻分不清楚 
}
/*----------LCA 相关操作----------*/ 
void dfs(int u,int f,int d){
	father[u] = f;dep[u] = d;top[u] = u;cnt[u] = 1;int mcnt = 0,son = 0;
	for(int i = first[u];i;i = edge[i].nt){
		int v = edge[i].v;if(v == f) continue;
		dfs(v,u,d + 1);cnt[u] += cnt[v];
		if(cnt[v] > mcnt) mcnt = cnt[v],son = v;
	}
	if(son) top[son] = u;
}

int find(int x){return top[x] == x ? x : top[x] = find(top[x]);}

int LCA(int x,int y){
	if(find(x) == find(y)) return dep[x] < dep[y] ? x : y;
	else return dep[top[x]] < dep[top[y]] ? LCA(x,father[top[y]]) : LCA(father[top[x]],y);
}
/*----------线段树模块----------*/
int build(){
	if(cnt_rab){cnt_rab--;return rab[cnt_rab];}
	++tot;return tot;
}

void Throw(int x) {tree[x].l = 0;tree[x].r = 0;tree[x].val[0] = 0,tree[x].val[1] = 0;rab[++cnt_rab] = x;} 

void modify(int l,int r,int &now,int pos,int val,int id){
	if(!now) now = build();
	if(l == r && l == pos){tree[now].val[id] += val;return;}
	int mid = (l + r) >> 1;
	if(pos <= mid) modify(l,mid,tree[now].l,pos,val,id);
	else modify(mid+1,r,tree[now].r,pos,val,id);
//	pushup(now);
} 

int query(int l,int r,int now,int pos,int id){
	if(!now) return 0;
	if(l == r && l == pos){return tree[now].val[id];}
	int mid = (l + r) >> 1;
	if(pos <= mid) return query(l,mid,tree[now].l,pos,id);
	else return query(mid+1,r,tree[now].r,pos,id);
}
/*----------线段树合并----------*/ 
void merge(int &x,int &y,int l,int r){
	if(!x) return;if(!y){y = x;return;}
	if(l == r) {tree[y].val[1] += tree[x].val[1];tree[y].val[0] += tree[x].val[0];return;}
	int mid = (l + r) >> 1;
	merge(tree[x].l,tree[y].l,l,mid);merge(tree[x].r,tree[y].r,mid + 1,r);
//	pushup(y);
}
/*//垃圾回收…… 
void merge(int x,int y,int l,int r){
	if(!x || !y) return x | y;int now = build();
	if(l == r) {
		tree[now].val[0] = tree[x].val[0] + tree[y].val[0];
		tree[now].val[1] = tree[x].val[1] + tree[y].val[1];
		return;
	}
	int mid = (l + r) >> 1;
	merge(tree[x].l,tree[y].l,l,mid);merge(tree[x].r,tree[y].r,mid + 1,r);
//	pushup(now);
	Throw(x);Throw(y);
}
*/
void merge_dfs(int u,int f){
	for(int i = first[u];i;i = edge[i].nt){
		int v = edge[i].v;if(v == f) continue;
		merge_dfs(v,u);merge(root[v],root[u],1,maxl);
	}
	if(dep[u] + w[u] <= maxl) ans[u] += query(1,maxl,root[u],dep[u] + w[u],0);//这里不能+n 
	ans[u] += query(1,maxl,root[u],w[u] - dep[u] + n + 1,1);
}
/*----------主模块----------*/ 
void work(){
	//初始化LCA 
	dfs(1,0,1);
	//修改 
	while(m -- ){
		int u,v,lca,d;read(u);read(v);
		lca = LCA(u,v);//以lca为界,分成两个部分分别加到线段树里 
		modify(1,maxl,root[u],dep[u],1,0);if(father[lca]) modify(1,maxl,root[father[lca]],dep[u],-1,0);
		modify(1,maxl,root[v],dep[u] - dep[lca]*2 + n + 1,1,1);modify(1,maxl,root[lca],dep[u] - dep[lca]*2 + n + 1,-1,1);
		//避免负数 
		//注意从1开始 
	}
	merge_dfs(1,0);
	for(int i = 1;i <= n; ++ i) 
		put(ans[i]),putchar(' ');
//	putchar('\n');
}

int main(){
//	freopen("testdata.in","r",stdin);
//	freopen("out.out","w",stdout);
//printf("%.4lf\n",sizeof(tree)/1024.0/1024);
	readdata();
	work();
	return 0;
}

Splay

#include<bits/stdc++.h>

using namespace std;

const int maxn = 1e5 + 5;
const int inf = 2e9 + 5;

int n,tot,root;
int father[maxn],child[maxn][3];
int size[maxn],cnt[maxn],val[maxn];

void file(){
	freopen("splay.in","r",stdin);
}

int chk(int now){
	return now == child[father[now]][1];
}

void pushup(int now){
	size[now] = size[child[now][0]] + size[child[now][1]] + cnt[now];
}

void rotate(int now){
	int fa = father[now],anc = father[fa],pos = chk(now),son = child[now][pos ^ 1];
	child[fa][pos] = son; father[son] = fa;
	child[anc][chk(fa)] = now; father[now] = anc;
	child[now][pos ^ 1] = fa; father[fa] = now;
	pushup(fa);pushup(now);
}

void Splay(int now,int aim = 0){
	while(father[now] != aim){
		int fa = father[now],anc = father[fa];
		if(anc != aim){
			if(chk(now) == chk(fa)) rotate(fa);
			else rotate(now);
		}
		rotate(now);
	}
	if(!aim) root = now;
}

void insert(int x){
	int now = root,fa = 0;
	while(now && val[now] != x){fa = now;now = child[now][x > val[now]];}
	if(now) ++cnt[now];
	else {
		now = ++tot;
		if(fa) child[fa][x > val[fa]] = now;
		size[now] = cnt[now] = 1;
		father[now] = fa;
		val[now] = x;
		child[now][0] = child[now][1] = 0;
	}
	Splay(now);
}

void find(int x){
	int now = root;
	while(child[now][x > val[now]] && val[now] != x) now = child[now][x > val[now]];
	Splay(now);
}

int get_kth(int k){
	int now = root;
	while(1){
		if(k <= size[child[now][0]]) now = child[now][0];
		else if(k > size[child[now][0]] + cnt[now]){
			k -= size[child[now][0]] + cnt[now];
			now = child[now][1];
		}else return now;
	}
}

int get_pre(int x){
	find(x);
	if(val[root] < x) return root;
	int now = child[root][0];
	while(child[now][1]) now = child[now][1];
	return now;
}

int get_suc(int x){
	find(x);
	if(val[root] > x) return root;
	int now = child[root][1];
	while(child[now][0]) now = child[now][0];
	return now;
}

void erase(int x){
	int pre = get_pre(x);
	int suc = get_suc(x);
	Splay(pre),Splay(suc,pre);
	int now = child[suc][0];
	--cnt[now];
	if(cnt[now]) Splay(now);
	else child[suc][0] = 0;
}

void work(){
	insert(-inf);
	insert(inf);
	while(n -- ){
		int opt,x;
		read(opt);read(x);
		switch(opt){
			case 1: {insert(x);break;}
			case 2: {erase(x);break;}
			case 3: {find(x);put(size[child[root][0]]);putchar('\n');break;}
			case 4: {put(val[get_kth(x + 1)]);putchar('\n');break;}//%%%
			case 5: {put(val[get_pre(x)]);putchar('\n');break;}
			default:{put(val[get_suc(x)]);putchar('\n');break;}
		}
	}
}

int main(){
//	file();
	read(n);
	work();
	return 0;
}

Vector

#include<bits/stdc++.h>

using namespace std;

vector<int>a;
int n,opt,x;

int main(){
	scanf("%d",&n);
	while(n --){
		scanf("%d%d",&opt,&x);
		switch(opt){
			case 1:{a.insert(lower_bound(a.begin(),a.end(),x),x);break;}
			case 2:{a.erase(lower_bound(a.begin(),a.end(),x));break;}
			case 3:{printf("%d\n",lower_bound(a.begin(),a.end(),x) - a.begin() + 1);break;}
			case 4:{printf("%d\n",a[x - 1]);break;}
			case 5:{printf("%d\n",*--lower_bound(a.begin(),a.end(),x));break;}
			default:{printf("%d\n",*upper_bound(a.begin(),a.end(),x));break;}
		}
	}
	return 0;
} 

multiset

#include<bits/stdc++.h>

using namespace std;

int x,n,opt;
multiset<int>s;

int main(){
	scanf("%d",&n);
	while(n -- ){
		scanf("%d%d",&opt,&x);
		switch(opt){
			case 1:{s.insert(x);break;}
			case 2:{s.erase(s.lower_bound(x));break;}
			case 3:{printf("%d\n",distance(s.begin(),s.lower_bound(x)) + 1);break;}
			case 4:{multiset<int>::iterator it = s.begin();advance(it,x - 1);printf("%d\n",*it);break;}
			case 5:{printf("%d\n",*--s.lower_bound(x));break;}
			default:{printf("%d\n",*s.upper_bound(x));break;}
		}
	}
	return 0;
}

分块

#include <bits/stdc++.h>

using namespace std;

const int maxn = 1e5+ 5;

long long n,m,t,l[maxn],r[maxn],pos[maxn];
long long a[maxn],sum[maxn],add[maxn];

void readdata(){
	read(n);read(m);
	for(int i = 1;i <= n; ++ i) read(a[i]);
}

void init(){
	for(int i = 1;i <= t; ++ i){
		l[i] = (i - 1) * t + 1;
		r[i] = i * t;
	}
	if(r[t] < n) t++,l[t] = r[t - 1] + 1,r[t] = n;
	for(int i = 1;i <= t; ++ i){
		for(int j = l[i];j <= r[i]; ++ j){
			pos[j] = i;sum[i] += a[j];
		}
	}
}

void change(int L,int R,long long d){
	int p = pos[L],q = pos[R];
	if(p == q){
		for(int i = L;i <= R; ++ i) a[i] += d;
		sum[p] += d * (R - L + 1);
	} else {
		for(int i = p + 1;i <= q - 1; ++ i) add[i] += d;
		for(int i = L;i <= r[p]; ++ i) a[i] += d;
		for(int i = l[q];i <= R; ++ i) a[i] += d;
		sum[p] += d * (r[p] - L + 1);
		sum[q] += d * (R - l[q] + 1);
	}
}

long long query(int L,int R){
	int p = pos[L],q = pos[R];
	long long ans = 0;
	if(p == q){
		for(int i = L;i <= R; ++ i) ans += a[i];
		ans += add[p] * (R - L + 1); //LR与PQ不能混 
	} else {
		for(int i = p + 1;i <= q - 1; ++ i) ans += sum[i] + add[i] * (r[i] - l[i] + 1);
		for(int i = L;i <= r[p]; ++ i) ans += a[i];
		for(int i = l[q];i <= R; ++ i) ans += a[i];
		ans += add[p] * (r[p] - L + 1); 
		ans += add[q] * (R - l[q] + 1); 
	}
	return ans;
}

void work(){
	
	t = sqrt(n);
	init();
	
	while(m -- ){
		char ch = getchar();
		while(ch != 'C' && ch != 'Q') ch = getchar();
		if(ch == 'C') {
			int  L,R;long long d;read(L);read(R);read(d);
			change(L,R,d);
		} else {
			int L,R;read(L);read(R);
			long long ans = query(L,R);
			put(ans);putchar('\n');
		}
	} 
}

int main(){
	readdata();
	work();
	return 0;
}

区间众数

#include <bits/stdc++.h>

using namespace std;

const int maxn = 4e4 + 2;
const int maxt = 205;//!!!!!!!越界会导致乱码或者其他数组乱码 

int n,m,t,tl,cn;
int tmp[maxn],a[maxn];
int pos[maxn],l[maxn],r[maxn];
int c[maxt][maxn],num[maxt][maxt],cnt[maxn];

void readdata(){
	read(n);read(m);
	for(int i = 1;i <= n; ++ i) read(a[i]),tmp[i] = a[i];
	sort(tmp + 1,tmp + n + 1);
	cn = unique(tmp + 1,tmp + n + 1) - (tmp + 1);
	for(int i = 1;i <= n; ++ i){
		a[i] = lower_bound(tmp + 1,tmp + cn + 1,a[i]) - tmp;//cn不是n 
	}
}

void init(){
	for(int i = 1;i <= t; ++ i){
		l[i] = (i-1) * tl + 1;
		r[i] = i * tl;
	}
	
	if(r[t] < n) t++,l[t] = r[t - 1] + 1,r[t] = n;
	//统计 
	for(int i = 1;i <= t; ++ i){
		int cur = 0;
		for(int j = l[i];j <= r[i]; ++ j){
			c[i][a[j]]++,pos[j] = i;
			if(c[i][a[j]] > cur || ((c[i][a[j]] == cur) && (a[j] < num[i][i]))) {cur = c[i][a[j]]; num[i][i] = a[j];}
			//num数组中存的是值不是位置 
		}//%%%%括号 
	}
	//前缀和 
	for(int i = 1;i <= t; ++ i)
		for(int j = 1;j <= cn; ++ j)
			c[i][j] += c[i - 1][j];
	//求区间众数 
	for(int i = 1;i <= t; ++ i)
		for(int j = i + 1;j <= t; ++ j){
			num[i][j] = num[i][j - 1];
			int cur = c[j - 1][num[i][j]] - c[i - 1][num[i][j]];
			/*
			for(int k = 1;k <= n; ++ k)
				if(c[j][k] - c[i - 1][k] > cur || ((c[j][k] - c[i - 1][k] == cur) && (k < num[i][j]))){
					//注意这里的k就是值 
					cur = c[j][k] - c[i - 1][k];
					num[i][j] = k;
				}
			*/
			//众数要么是块i~j-1的众数,要么是块j中出现的数 
			for(int k = l[j];k <= r[j]; ++ k){
				if(c[j][a[k]] - c[i - 1][a[k]] > cur || ((c[j][a[k]] - c[i - 1][a[k]] == cur) && (a[k] < num[i][j]))) {
					cur = c[j][a[k]] - c[i - 1][a[k]];
					num[i][j] = a[k];
				}
			}
		}
}

int query(int L,int R){
	int p = pos[L],q = pos[R];
	if(p == q){
		int cur = 0,ans = 0;;
		for(int i = L;i <= R; ++ i){
			cnt[a[i]]++;
			if(cnt[a[i]] > cur || ((cnt[a[i]] == cur) && (a[i] < ans))) cur = cnt[a[i]],ans = a[i];
		}
		for(int i = L;i <= R; ++ i) cnt[a[i]] = 0;
		//清零 
		return ans;
	} else {
		int ans = num[p+1][q-1];
		int cur = c[q-1][ans] - c[p][ans];
		for(int i = L;i <= r[p]; ++ i) {
			if(!cnt[a[i]]) cnt[a[i]] = c[q-1][a[i]] - c[p][a[i]] + 1;
			else cnt[a[i]]++;
			if(cnt[a[i]] > cur || ((cnt[a[i]] == cur) && (a[i] < ans))) cur = cnt[a[i]],ans = a[i];
		}
		for(int i = l[q];i <= R; ++ i) {
			if(!cnt[a[i]]) cnt[a[i]] = c[q-1][a[i]] - c[p][a[i]] + 1;
			else cnt[a[i]]++;
			if(cnt[a[i]] > cur || ((cnt[a[i]] == cur) && (a[i] < ans))) cur = cnt[a[i]],ans = a[i];
		}
		for(int i = L;i <= r[p]; ++ i) cnt[a[i]] = 0;
		for(int i = l[q];i <= R; ++ i) cnt[a[i]] = 0;
		
//		cout << "debug : " << cur << endl;
		return ans;
	}
}

void work(){
	
	t = sqrt(n); tl = n/t;
	init();
	int x = 0;
	while(m -- ){
		int L, R;read(L);read(R);
		L = (L + x - 1) % n + 1;
		R = (R + x - 1) % n + 1;
		if(L > R) swap(L,R);
		int ans = query(L,R);
		put(tmp[ans]);putchar('\n');
		
//		if(tmp[ans] == 58252620) cout << "debug : " << L << " " << R << endl;
		x = tmp[ans];//还原tmp 
	}
}

int main(){
//	freopen("testdata(1).in","r",stdin);
//	freopen("out.out","w",stdout);
	readdata();
	work();
	return 0;
}

莫队

/*******************
User:Mandy
Language:c++
Problem:luogu
Algorithm: 
*******************/
#include<bits/stdc++.h>

using namespace std;

const int maxn = 5e4 + 5;
const int maxt = 250;

int n,m,t,tl,curl,curr;
int a[maxn],l[maxt],r[maxt],pos[maxn];
int c[maxn];
long long ans = 0;
long long Ans[maxn],Ans1[maxn];

struct Query{
	int l,r,id;
}ask[maxn];

void readdata(){
	read(n);read(m);
	t = n / sqrt((double)m * 2.0 / 3.0);tl = n / t;
	for(int i = 1;i <= n; ++ i) read(a[i]),pos[i] = (i - 1) / tl + 1;
}

bool cmp(const Query &x,const Query &y){
	return pos[x.l] ^ pos[y.l] ? pos[x.l] < pos[y.l] : (pos[x.l] & 1 ? x.r < y.r : x.r > y.r); 
}

void add(int x){
	ans = ans - (long long)c[x] * (c[x] - 1) + (long long)c[x] * (c[x] + 1);
	c[x] ++;
}

void del(int x){
	ans = ans - (long long)c[x] * (c[x] - 1) + ((long long)c[x] - 1) * (c[x] - 2);
	c[x] --;
}

long long gcd(long long x,long long y){
	return (x % y) ? gcd(y,x % y) : y;
}

void work(){
	for(int i = 1;i <= m; ++ i){
		read(ask[i].l);read(ask[i].r);ask[i].id = i;
	}
	sort(ask + 1,ask + m + 1,cmp);
	curl = curr = 1; ans = 0;c[a[1]] = 1;
	for(int i = 1; i <= m; ++ i){
		while(ask[i].l < curl) add(a[--curl]);
		while(ask[i].l > curl) del(a[curl]),++curl;
		while(ask[i].r < curr) del(a[curr]),--curr;
		while(ask[i].r > curr) add(a[++curr]);
		Ans[ask[i].id] = ans;Ans1[ask[i].id] = ((long long)ask[i].r - ask[i].l + 1) * (ask[i].r - ask[i].l);
	}
	for(int i = 1;i <= m; ++ i){
		if(Ans[i] == 0) puts("0/1");
		else {
			long long d = gcd(Ans[i],Ans1[i]);
			put(Ans[i]/d);putchar('/');put(Ans1[i]/d);putchar('\n');
		}
	}
}

int main(){
	readdata();
	work();
	return 0;
}

欧拉路

luogu1341

#include<bits/stdc++.h>

using namespace std;

int n,num;
int edge[130][130],d[130],ans[1400];

void docu(){
	freopen("1341.txt","r",stdin);
}

void readdata(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i){
		char s[5];
		scanf("%s",s);
		edge[s[0]][s[1]]=1;
		edge[s[1]][s[0]]=1;
		++d[s[0]];++d[s[1]];
	}
}

void dfs(int u){
	for(int i=1;i<=130;++i){
		if(edge[u][i]){
			edge[u][i]=edge[i][u]=0;
			dfs(i);
		}
	}
	ans[++num]=u;
}

void work(){
	int start=0,cnt=0;
	for(int i=1;i<=130;++i){
		if(d[i]&1){
			++cnt;
			if(!start) start=i;
		}
	}
	
	if(cnt&&cnt!=2){
		puts("No Solution");
		return;
	}
	
	if(!start) 
		for(int i=1;i<=130;++i)
			if(d[i]){
				start=i;
				break;
			}
	
	dfs(start);
	
	if(num!=n+1){
		puts("No Solution");
		return ;
	}
	
	for(int i=num;i>=1;--i){
		printf("%c",ans[i]);
	}
}

int main(){
//	docu();
	readdata();
	work();
	return 0;
}

离散化

int a[n], b[n], sub[n];
// a[n]是即将被离散化的数组,b[n]是a[n]的副本,sub用于排序去重后提供离散化后的值
sort(sub, sub + n);
int size = unique(sub, sub + n) - sub;
for(int i = 0; i < n; i++)
    a[i] = lower_bound(sub, sub + size, a[i]) - sub;
 //即a[i]为b[i]离散化后对应的值

结构体

struct Node{
	int x,y,d;
	Node(){x = y = 0;d = 0;}
	Node(int _x,int _y,int _d):x(_x),y(_y),d(_d){}//记得打冒号: 
	//Node(int _x = 0,int _y = 0,int _d = 0):x(_x),y(_y),d(_d){}
	bool operator <(const Node &a)const {
		return d > a.d;//优队里从小到大排
	}//emm,d > a.d;
	//优先队列里默认是从大到小,所以return d > a.d;
	//在sort里默认是从小到大,所以要从小到大应该为return d < a.d;
}s,t;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值