这里写目录标题
数据结构
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;
}
线段树
推荐阅读
区间加,区间和
题目: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;
}
区间加,区间乘,区间和
/*
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;
}
区间开方
/***********************
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;
}
区间最值,区间加,区间整除
/*****************************
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;