ACM数据结构部分模版.docx
《ACM数据结构部分模版.docx》由会员分享,可在线阅读,更多相关《ACM数据结构部分模版.docx(40页珍藏版)》请在冰豆网上搜索。
ACM数据结构部分模版
数据结构:
增加栈
#pragmacomment(linker,"/STACK:
1024000000,1024000000")
二维树状数组
#include
#include
#include
#definemaxn130
usingnamespacestd;
intxt[maxn][maxn][maxn];
intadd,z,n;
intlow(intx)
{
returnx&(-x);
}
//二维树状数组,第三维枚举
voidup(intx,inty)
{
inti,j;
for(i=x;i<=maxn;i+=low(i))
for(j=y;j<=maxn;j+=low(j))
{
xt[z][i][j]+=add;
if(xt[z][i][j]<0)xt[z][i][j]=0;
}
}
intsum(intx,inty)
{
inti,ans=0;
for(i=x;i>0;i-=low(i))
for(intj=y;j>0;j-=low(j))
{
ans+=xt[z][i][j];
}
returnans;
}
intmain()
{
intx,y,a;
intx1,y1,z1,z2;
intx2,y2,ans;
while(cin>>n)
{
memset(xt,0,sizeof(xt));
while(scanf("%d",&a)&&a!
=3)
{
ans=0;
if(a==1)
{
scanf("%d%d%d%d",&x,&y,&z,&add);
x+=2;y+=2;z+=2;
up(x,y);
}
elseif(a==2)
{
scanf("%d%d%d",&x1,&y1,&z1);
scanf("%d%d%d",&x2,&y2,&z2);
//树状数组必须大于0,而且是整数
x1+=2;x2+=2;y1+=2;y2+=2;z1+=2;z2+=2;
for(z=z1;z<=z2;z++)
{//求矩阵(x1,y1)(x2,y2)(对角)的和公式
//sum(x2,y2)-sum(x1-1,y2)-sum(x2,y1-1)+sum(x1-1,y1-1)
ans+=(sum(x2,y2)-sum(x1-1,y2)-sum(x2,y1-1)+sum(x1-1,y1-1));
}
printf("%d\n",ans);
}
}
线段树成段更新
voiddown(into,intL,intR)
{
if(add[o]!
=0)
{
sum[o]+=add[o]*(R-L+1);
}
}
voidupdate(intL,intR,into)
{
if(L>=ql&&qr>=R)
{
add[o]+=v;
sum[o]+=v*(R-L+1);
return;
}
intmid=(L+R)>>1;
if(ql<=mid)update(L,mid,o<<1);
if(qr>mid)update(mid+1,R,o<<1|1);
sum[o]=sum[o<<1]+sum[o<<1|1];
down(o,L,R);
}
voidfind(intL,intR,into,LL_add)
{
if(L>=ql&&qr>=R)
{
v+=sum[o];
v+=_add*(R-L+1);
return;
}
intmid=(L+R)>>1;
if(ql<=mid)find(L,mid,o<<1,_add+add[o]);
if(qr>mid)find(mid+1,R,o<<1|1,_add+add[o]);
}
voidpush(into)
{
intlc=o*2;intrc=o*2+1;
if(set[o]>=0)//往下更新
{
set[lc]=set[rc]=set[o];
set[o]=-1;//记得标记
}
}
voidupdate(into,intL,intR)
{
intlc=o*2,rc=o*2+1;
if(x1<=L&&x2>=R)
{
set[o]=v;
}
else
{
push(o);//把之前没有更新的一起带下去更新
intmid=(L+R)/2;
if(x1<=mid)update(lc,L,mid);
if(x2>mid)update(rc,mid+1,R);
}
}
//求居间不同数个数
voidfind(into,intL,intR)
{
if(set[o]!
=-1)
{
if(set[o]>0&&!
vi[set[o]])
{
vi[set[o]]=1;
mun++;
}//如果当前有标记则不再往下找
return;
}
if(L==R)return;
intmid=(L+R)>>1;
find(o*2,L,mid);
find(o*2+1,mid+1,R);
}
KMP:
voidget()
{
inti,j=-1;
f[0]=-1;
for(i=1;iwhile(j>=0&&p[j+1]!
=p[i])j=f[j];
if(p[j+1]==p[i])j++;
f[i]=j;
}
}
voidfind()
{
inti,j=-1;
get();
for(i=0;iwhile(j>=0&&p[j+1]!
=T[i])j=f[j];
if(p[j+1]==T[i])j++;
if(j==m-1){
mun++;
j=-1;
}
}
}
intmain()
{
while(scanf("%s",T)!
=EOF){
if(T[0]=='#'&&strlen(T)==1)break;
n=strlen(T);
scanf("%s",p);
m=strlen(p);
mun=0;
find();
cout<}
}
差分约束
//用SPFA解差分方程,用最短路径求差分方程的最大解;用最长路径求差分方程的最小解.
//d[t+1]-d[s]>=c,也就是dist[t+1]>=dist[s]+c,
//这是求最长路的形式,所以要求最长路//看形势
voidspfa(intMax,intMin)
{
inti,j,now;
intu,w;
memset(vi,0,sizeof(vi));
queueq;
for(i=Min;i<=Max;i++)
d[i]=-INF;//因为求最长路
d[Min]=0;
q.push(Min);
vi[1]=Min;
while(!
q.empty())
{
now=q.front();
q.pop();
for(i=0;i{
piia=qe[now][i];
u=a.first;
w=a.second;
if(d[u]{
d[u]=w+d[now];
if(!
vi[u])
{
q.push(u);
vi[u]=1;
}
}
}
vi[now]=0;
}
}
intmain()
{
inti,j,n,m;
intu,v,w,len,Max=MAX,Min;
while(scanf("%d",&n)!
=EOF)
{
for(i=0;i<=Max;i++)
qe[i].clear();
Max=0;Min=INF;
for(i=1;i<=n;i++)
{
scanf("%d%d%d",&u,&v,&w);
qe[u].push_back(pii(v+1,w));
if(v+1>Max)
Max=v+1;
if(u}
for(i=Min;i{
qe[i+1].push_back(pii(i,-1));
qe[i].push_back(pii(i+1,0));
}
spfa(Max,Min);
cout<printf("%d\n",d[Max]-d[Min]);
}
}
LCA离线算法
typedefpairpii;
vectormap[M],query[M];
intfa[M],dis[M],ans[M];
boolvi[M];
intn,m;
voidin()
{
inta,b,c,i;
charqq;
cin>>m;
for(i=0;iscanf("%d%d%d%c",&a,&b,&c,&qq);
map[a].push_back(pii(b,c));
map[b].push_back(pii(a,c));
}
cin>>m;
for(i=0;iscanf("%d%d",&a,&b);
query[a].push_back(pii(b,i));//这就是离线
query[b].push_back(pii(a,i));
}
memset(vi,0,sizeof(vi));
}
intfind(intx){
if(fa[x]!
=x)
fa[x]=find(fa[x]);
returnfa[x];
}
voiddfs(intu,intlen){
fa[u]=u;//往下找防止找到最后父亲
dis[u]=len;
vi[u]=1;
inti,j;
for(i=0;i