NOIP2019翻车前写(and 抄)过的代码

咕咕咕。按上传时间升序排列。


//树的重心
void dfs(int x) {
    v[x]=1; size[x]=1;
    int max_part=0;
    for(int i=hed[x];i;i=nxt[i])
    {
        int y=ver[i];
        if(v[y]) continue;
        dfs(y); size[x]+=size[y];
        max_part=max(max_part,size[y]);
    }
    max_part=max(max_part,n-size[x]);
    if(max_part<ans) {
        ans=max_part;
        ans_node=x;
    }
}
//推箱子,没AC
#include<bits/stdc++.h>
using namespace std;
const int maxn=31;

char s[maxn][maxn];
int n,m;

struct node{
	int x,y,dir;
}st[7],ed[7];
int stcnt,edcnt;

struct node2{
	int x,y;
}manst;

int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
int ddir[4]={1,0,3,2};

node pre_box[maxn][maxn][4];
int min_box[maxn][maxn][4],min_man[maxn][maxn][4];

bool valid(int x,int y)
{
	if(x<1||x>n||y<1||y>m) return false;
	return s[x][y]=='#' ? false : true;
}

bool connect(int r,int c)//man to r,c
{
	int vis[maxn][maxn]={0}; vis[manst.x][manst.y]=1;
	queue<node2>q;
	q.push(manst);
	while(!q.empty())
	{
		node2 u=q.front();q.pop();
		if(u.x==r&&u.y==c) return true;
		for(int i=0;i<4;++i)
		{
			node2 v=(node2){u.x+dx[i],u.y+dy[i]};
			if(!valid(v.x,v.y)||vis[v.x][v.y]) continue;
			q.push(v); vis[v.x][v.y]=1;
		}
	}
	return false;
}

void findsted()
{
	stcnt=edcnt=0;
	for(int i=1;i<=n;++i)
	for(int j=1;j<=m;++j)
	{
		if(s[i][j]=='S') {
			s[i][j]='.';
			manst.x=i,manst.y=j;
		}
		if(s[i][j]=='T') {
			s[i][j]='.';
			for(int D=0;D<4;++D) {
				if(valid(i+dx[D],j+dy[D])) {
					ed[++edcnt]=(node){i,j,D};
				}
			}
		}
	}
	for(int i=1;i<=n;++i)
	for(int j=1;j<=m;++j)
	{
		if(s[i][j]=='B') {
			s[i][j]='.';
			for(int D=0;D<4;++D) {
				if(valid(i+dx[D],j+dy[D])) {
					s[i][j]='#';
					if(connect(i+dx[D],j+dy[D]))
					st[++stcnt]=(node){i,j,D};
					s[i][j]='.';
				}
			}
		}
	}
}

int getstep(node U,node V)
{
	node2 S=(node2){U.x+dx[U.dir],U.y+dy[U.dir]};
	node2 T=(node2){U.x+dx[V.dir],U.y+dy[V.dir]};
	int step[maxn][maxn]; memset(step,-1,sizeof step);
	queue<node2>q;
	q.push(S); step[S.x][S.y]=0;
	while(!q.empty())
	{
		node2 u=q.front();q.pop();
		if(u.x==T.x&&u.y==T.y) return step[u.x][u.y];
		for(int i=0;i<4;++i)
		{
			node2 v=(node2){u.x+dx[i],u.y+dy[i]};
			if(!valid(v.x,v.y)||step[v.x][v.y]!=-1) continue;
			q.push(v); step[v.x][v.y]=step[u.x][u.y]+1;
		}
	}
	return -1;
}

int getstep(node2 U,node V)
{
	node2 T=(node2){V.x+dx[V.dir],V.y+dy[V.dir]};
	int step[maxn][maxn]; memset(step,-1,sizeof step);
	queue<node2>q;
	q.push(U); step[U.x][U.y]=0;
	while(!q.empty())
	{
		node2 u=q.front();q.pop();
		if(u.x==T.x&&u.y==T.y) return step[u.x][u.y];
		for(int i=0;i<4;++i)
		{
			node2 v=(node2){u.x+dx[i],u.y+dy[i]};
			if(!valid(v.x,v.y)||step[v.x][v.y]!=-1) continue;
			q.push(v); step[v.x][v.y]=step[u.x][u.y]+1;
		}
	}
	return -1;
}

bool is_ans(node u)
{
	for(int i=1;i<=edcnt;++i)
	if(ed[i].x==u.x&&ed[i].y==u.y&&ed[i].dir==u.dir) return true;
	return false;
}

int solve()
{
    int jd=-1;
	memset(min_box,63,sizeof min_box);
	memset(min_man,63,sizeof min_man);
	queue<node>q;
	for(int i=1;i<=stcnt;++i)
	{
		q.push(st[i]);
		min_box[st[i].x][st[i].y][st[i].dir]=0;
		s[st[i].x][st[i].y]='#';
		min_man[st[i].x][st[i].y][st[i].dir]=getstep(manst,st[i]);
		s[st[i].x][st[i].y]='.';
		pre_box[st[i].x][st[i].y][st[i].dir].x=0;
	}
	while(!q.empty())
	{
		node u=q.front();q.pop();
// 		printf("u(%d,%d)
",u.x,u.y);
		if(is_ans(u)) jd=1;
		for(int i=0;i<4;++i)
		{
			node v=(node){u.x+dx[i],u.y+dy[i],ddir[i]};
			if(!valid(v.x,v.y) || !valid(u.x+dx[v.dir],u.y+dy[v.dir])) continue;
			if(min_box[u.x][u.y][u.dir]+1>min_box[v.x][v.y][v.dir]) continue;
			s[u.x][u.y]='#';
			int step=getstep(u,v);
			s[u.x][u.y]='.';
			if(step==-1) continue;
			if(min_box[u.x][u.y][u.dir]+1==min_box[v.x][v.y][v.dir]&&
			min_man[u.x][u.y][u.dir]+step>min_man[v.x][v.y][v.dir]) continue;
			min_box[v.x][v.y][v.dir]=min_box[u.x][u.y][u.dir]+1;
			min_man[v.x][v.y][v.dir]=min_man[u.x][u.y][u.dir]+step;
			pre_box[v.x][v.y][v.dir]=u;
			q.push(v);
		}
	}
	return jd;
}

void putlina(int ind)
{
    switch(ind)
    {
        case 0:cout<<'s';break;
        case 1:cout<<'n';break;
        case 2:cout<<'e';break;
        case 3:cout<<'w';break;
    }
}

void putlinA(int ind)
{
    switch(ind)
    {
        case 0:cout<<'S';break;
        case 1:cout<<'N';break;
        case 2:cout<<'E';break;
        case 3:cout<<'W';break;
    }
}

void road(int sx,int sy,int ex,int ey)
{
    int pre[maxn][maxn]; memset(pre,-1,sizeof pre);
    pre[sx][sy]=-2; queue<node2>q; q.push((node2){sx,sy});
    while(!q.empty())
    {
        node2 u=q.front(); q.pop();
        if(u.x==ex&&u.y==ey)
        {
            stack<int>sta;
            while(pre[u.x][u.y]!=-2) {
                sta.push(pre[u.x][u.y]);
                int d=pre[u.x][u.y];//
                u.x+=dx[d], u.y+=dy[d];
            }
            while(!sta.empty())
            {
                putlina(sta.top());
                sta.pop();
            }
            return;
        }
        for(int i=0;i<4;++i) {
            node2 v=(node2){u.x+dx[i],u.y+dy[i]};
            if(!valid(v.x,v.y)) continue;
            if(pre[v.x][v.y]!=-1) continue;
            q.push(v); pre[v.x][v.y]=ddir[i];
        }
    }
}

void out()
{
    stack<node>sta;
    int boxx=1010010101,mann=1010010101,i;
    for(int j=1;j<=edcnt;++j)
    if(min_box[ed[j].x][ed[j].y][ed[j].dir]<boxx ||
    min_box[ed[j].x][ed[j].y][ed[j].dir]==boxx&&min_man[ed[j].x][ed[j].y][ed[j].dir]<mann)
    {
        boxx=min_box[ed[j].x][ed[j].y][ed[j].dir];
        mann=min_man[ed[j].x][ed[j].y][ed[j].dir];
        i=j;
    }
    node u=ed[i];
    while(u.x) sta.push(u), u=pre_box[u.x][u.y][u.dir];
    vector<node>vec;
    while(!sta.empty()) {
        vec.push_back(sta.top());
        sta.pop();
    }
    s[st[1].x][st[1].y]='#';
    road(manst.x,manst.y,vec[0].x+dx[vec[1].dir],vec[0].y+dy[vec[1].dir]);
    s[st[1].x][st[1].y]='.';
    putlinA(vec[1].dir);
    for(int k=2;k<(int)vec.size();++k) {
        s[vec[k-1].x][vec[k-1].y]='#';
        road(vec[k-1].x+dx[vec[k-1].dir],vec[k-1].y+dy[vec[k-1].dir],vec[k-1].x+dx[vec[k].dir],vec[k-1].y+dy[vec[k].dir]);
        s[vec[k-1].x][vec[k-1].y]='.';
        putlinA(vec[k].dir);
    }
    return;
}

int main()
{
	int T=0;
	while(scanf("%d%d",&n,&m)==2 && n)
	{
		memset(s,0,sizeof s);
		for(int i=1;i<=n;++i) scanf("%s",s[i]+1);
		findsted();
		printf("Maze #%d
",++T);
  		if(solve()==-1) printf("Impossible.

");
  		else
		out(),printf("

");
	}
}
//食物鏈
#include<bits/stdc++.h>
using namespace std;
const int maxn=50005;

int fa[maxn*3];
int n,k,ans;

int fid(int x)
{return fa[x]==x ? x : fa[x]=fid(fa[x]);}
void merge(int i,int j)
{
    i=fid(i),j=fid(j);
    fa[i]=j;
}

int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1;i<=3*n;++i) fa[i]=i;

    for(int i=1;i<=k;++i)
    {
        int d,x,y;
        scanf("%d%d%d",&d,&x,&y);
        if(x>n||y>n) {ans++;continue;}
        int x_a=x,x_b=x+n,x_c=x+n+n;
        int y_a=y,y_b=y+n,y_c=y+n+n;
        if(d==1)
        {
            //jd
            int lowe=(fid(x_a)==fid(y_b))||(fid(x_b)==fid(y_c))||(fid(x_c)==fid(y_a));
            int uppe=(fid(y_a)==fid(x_b))||(fid(y_b)==fid(x_c))||(fid(y_c)==fid(x_a));
            if(lowe||uppe) {ans++;continue;}
            //make
            merge(x_a,y_a);
            merge(x_b,y_b);
            merge(x_c,y_c);
        }
        else
        {
            //jd
            if(x==y) {ans++;continue;}
            int case1=(fid(y_a)==fid(x_b))||(fid(y_b)==fid(x_c))||(fid(y_c)==fid(x_a));
            int case2=(fid(x_a)==fid(y_a))||(fid(x_b)==fid(y_b))||(fid(x_c)==fid(y_c));
            if(case1||case2) {ans++;continue;}
            //make
            merge(x_a,y_b);
            merge(x_b,y_c);
            merge(x_c,y_a);
        }
    }
    cout<<ans;
    return 0;
//小trick……樹狀數組O(n)初始化,原理是每个以i为标号的节点的值为其子节点的值之和与$a_i$的值的和
void init()
{
    for(int i=1;i<=n;++i)
    {
        t[i]+=a[i];
        int j;if(j=i+lowbit(i)<=n) t[j]+=t[i];
    }
}
//大trick:树状数组区间加法、区间求和(烂大街)
void add(int x,int val)
{
    for(int i=x;i<=n;i-=lowbit(i)) {
        d1[i]+=val;
        d2[i]+=val*x;
    }
}

int ask(int x)
{
    int res=0;
    for(int i=x;i>=1;i-=lowbit(i)) {
        res+=(x+1)*d1[i];
        res+=d2[i];
    }
    return res
}
//小trick:权值树状数组查询kth(树状数组上倍增)(O (log n))
int kth(int k)
{
    int cnt=0,ret=0;
    for(int i=log2(n);~i;--i)
    {
        ret+=1<<i;
        if(ret>=n||cnt+t[ret]>=k)
            ret-=1<<i;
        else
            cnt+=t[ret];
    }
    return ret + 1;
}
//权值树状数组上倍增(谜一般的牛)
#include<bits/stdc++.h>
using namespace std;
const int maxn=100005;


int t[maxn],n,a[maxn];
int ans[maxn];

int que(int k)
{
    int ret=0,sum=0;
    for(int i=log2(n)+1;~i;--i)
    {
    	if(ret+(1<<i)<=n && sum+t[ret+(1<<i)]<k)
    	sum+=t[ret+(1<<i)], ret+=1<<i;
    }
    return ret+1;
}

void del(int x)
{
    for(int i=x;i<=n;i+=i&-i) {
    	t[i]--;
	}
}

int main()
{
    scanf("%d",&n); for(int i=2;i<=n;++i) scanf("%d",&a[i]);
    a[1]=0;
    for(int i=1;i<=n;++i) {
        t[i]+=1;
        int j=i+(i&-i);
        if(j<=n) t[j]+=t[i];
    }
    for(int i=n;i>=1;--i)
    {
        ans[i]=que(a[i]+1);
        del(ans[i]);
    }
    for(int i=1;i<=n;++i) cout<<ans[i]<<'
';
    return 0;
}
//kruskal最小生成树算法板子(O(m log m))
struct rec{int x,y,z;}edge[500010];
int fa[100010],n,m,ans;
bool operator < (rec a,rec b)
{
    return a.z<b.z;
}
int get(int x)
{
    if(fa[x]==x) return x;
    return fa[x]=get(fa[x]);
}
int main() {
    cin>> n >> m;
    for(int i=1;i<=m;++i) scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].z);
    sort(edge+1,edge+1+m);
    for(int i=1;i<=n;++i) fa[i]=i;
    for(int i=1;i<=m;++i) {
           int x=get(edge[i].x);
            int y=get(edge[i].y);
        if(x==y) continue;
        fa[x]=y;
        ans+=edge[i].z;
    }
    cout<<ans;
    return 0;
}
//堆优化 prim 最小生成树(抄别人的代码,这马蜂我受不了啊)
struct node{
	int t;int d;
	bool operator < (const node &a) const
	{
		return !(d<a.d);
	}
};

int n,m;
int vis[maxn];
vector<node>e[maxn];
priority_queue<node>q;

ll pirm()
{
	ll ans=0;
	int cnt=0;
	q.push((node){1,0});
	while(!q.empty()&&cnt<=n)
	{
		node k=q.top(); q.pop();
		if(vis[k]) continue;
		vis[k]=1;
		ans+=k.d;
		cnt++;
		for(int i=0;i<e[k.t].size();++i)
		{
			if(!vis[e[k.t][i].t]) {
				q.push((node){e[k.t][i].t,e[k.t][i].d})
			}
		}
	}
	return ans;
}
//最短路斗笔题,9.29被卡智商了,看来这几天智商还是有提高的。(It's not a bug, it's a feature!(Uva658))
#include<bits/stdc++.h>
using namespace std;
struct fix{
	char pre[21],nxt[21];
	int t;
}fixs[111];

int n,m;
long long d[(1<<20)+5];
bool vis[(1<<20)+5];

struct heapnode{
	int t, bugstyle;
};
bool operator <(heapnode a,heapnode b)
{
	return !(a.t<b.t);
}
int solve()
{
	priority_queue<heapnode>q; q.push((heapnode){0, (1<<n)-1});
	for(int i=0;i<=(1<<n)-1;++i) d[i]=2147483647; d[(1<<n)-1]=0;
	memset(vis,0,sizeof vis);
	while(!q.empty())
	{
		heapnode u=q.top(); q.pop();
		if(vis[u.bugstyle]) continue; vis[u.bugstyle]=1;
		for(int i=1;i<=m;++i)
		{
			bool canbeput = true;
			for(int j=0;j<n;++j) if(fixs[i].pre[j]=='+'&& !(u.bugstyle & (1<<j))) {canbeput=false; break;}
			for(int j=0;j<n;++j) if(fixs[i].pre[j]=='-'&&  (u.bugstyle & (1<<j))) {canbeput=false; break;}
			if(!canbeput) continue;
			heapnode v=(heapnode) {fixs[i].t+d[u.bugstyle],u.bugstyle};
			for(int j=0;j<n;++j) {
				if(fixs[i].nxt[j]=='+') {v.bugstyle |=  (1<<j);}
				if(fixs[i].nxt[j]=='-') {v.bugstyle &= ~(1<<j);}
			}
			if(d[v.bugstyle]>v.t) {
				d[v.bugstyle]=v.t;
				q.push(v);
			}
		}
	}
	if(d[0]==2147483647)
	return -1;
	else
	return d[0];
}

int main()
{
	int id=0;
	while(scanf("%d%d",&n,&m)==2&& n|m)
	{
		for(int i=1;i<=m;++i) scanf("%d%s%s",&fixs[i].t,fixs[i].pre,fixs[i].nxt);
		printf("Product %d
",++id);
		int ans=solve();
		if(ans<0) printf("Bugs cannot be fixed.

");
		else printf("Fastest sequence takes %d seconds.

",ans);
	}
	return 0;
}
//联通块间最短路(BZOJ2200)
#include<bits/stdc++.h>
using namespace std;
const int maxn=25005;
const int maxm=50005;

int t,r,p,s;
int cnt,c[maxn], deg[maxn];

int ct,ver[maxm<<2],val[maxm<<2],hed[maxm<<2],nxt[maxm<<2];
void add(int a,int b,int c)
{
    ver[++ct]=b; val[ct]=c;
    nxt[ct]=hed[a]; hed[a]=ct;
}

void tag_it(int u)
{
    c[u]=cnt;
    for(int i=hed[u];i;i=nxt[i])
    {
        int v=ver[i]; if(c[v]) continue;
        tag_it(v);
    }
}

void get_c()
{
    for(int i=1;i<=t;++i)
    if(!c[i]) {cnt++;tag_it(i);}
}


int vis[maxn];
long long d[maxn];

void dij(int block,queue<int> &buff);
void topo_sort_and_dij()
{
    queue<int> buff;
    for(int i=1;i<=cnt;++i) if(!deg[i]) buff.push(i);
    while(!buff.empty())
    {
        int u=buff.front(); buff.pop();
        dij(u,buff);
    }
}



struct heapnode{
    long long d;
    int x;
};
bool operator <(heapnode a,heapnode b)
{
    return !(a.d<b.d);
}
void dij(int block,queue<int> &buff)
{
    priority_queue<heapnode>Q;
    for(int i=1;i<=t;++i)
        if(c[i]==block) Q.push((heapnode){d[i],i});
    while(!Q.empty())
    {
        int u=Q.top().x; Q.pop();
        if(vis[u]) continue; else vis[u]=true;
        for(int i=hed[u];i;i=nxt[i])
        {
            int v=ver[i];
            if(d[v]>d[u]+val[i]) {
                d[v]=d[u]+val[i];
                if(c[u]==c[v]) Q.push((heapnode){d[v],v});
            }
            if(c[u]!=c[v]) {
                deg[c[v]]--;
                    if(!deg[c[v]]) buff.push(c[v]);
            }
        }
    }
}

void out_ans()
{
    for(int i=1;i<=t;++i)
    if(d[i]>=2000000000)
    printf("NO PATH
");
    else
    printf("%lld
",d[i]);
}

int main()
{
    scanf("%d%d%d%d",&t,&r,&p,&s);
    for(int i=1;i<=r;++i) {int a,b,z; scanf("%d%d%d",&a,&b,&z);add(a,b,z); add(b,a,z);}
    get_c();
    for(int i=1;i<=p;++i) {int a,b,z; scanf("%d%d%d",&a,&b,&z);add(a,b,z); deg[c[b]]++;}
    for(int i=1;i<=t;++i) d[i]=2147483647;
    d[s]=0;
    topo_sort_and_dij();
    out_ans();
    return 0;
}
//Bellman-Ford的队列优化
bool bellman_ford()
{
	queue<int>Q;
	memset(inq,0,sizeof inq);
	memset(cnt,0,sizeof cnt);
	for(int i=1;i<=n;++i) d[i] = INF;
	d[start]=0;
	q.push(start); inq[start] = true;
	while(!q.empty())
	{
		int u=q.front(); q.pop(); inq[u] = false;
		for(int i=0;i<(int)G[u].size();++i) { Edge& e=edges[G[u][i]];
									if(d[u]<INF && d[e.to]>d[u]+e.dist) {
									d[e.to]=d[u]+e.dist;
									if(!inq[e.to]) {Q.push(e.to); inq[e.to]=true;
							   						if(++cnt[e.to]>n) return false;
							   						}
									}
		}
	}
	return true;
}
//floyed板子
int d[310][310], n, m;
int main() {
	cin >> n >> m;
	memset(d, 0x3f, sizeof d);
	for(int i=1;i<=n;++i) d[i][i]=0;
	for(int i=1;i<=m;++i) {
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		d[x][y]=min(d[x][y],z);
	}
	for(int k=1;k<=n;++k)
		for(int i=1;i<=n;++i)
			for(int j=1;j<=n;++j)
				d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
}
int era(int *primes,int lim) // 求1-n的所有素数,保存在primes里,返回primes中的素数个数。
{
	int v[maxlim]={0}, cnt=0;
	int m=sqrt(lim+0.5);
	for(int i=2;i<=m;++i)
	if(!vis[i]) {
		primes[++cnt]=i;
		for(int j=i*i;j<=lim;j+=i)
			v[j]=1;
	}
	return cnt;
}
//试除法求n的正约数集合
int factor[1010], m=0;
for(int i=1;i*i<=n;++i) {
	if(n%i==0) {
		factor[++m]=i;
		if(n/i != i) factor[++m]=n/i;
	}
}
//倍数法求1-n的正约数集合
vector<int>factor[70707];
for(int i=1;i<=n;++i)
	for(int j=i;j<=n;j+=i)
		factor[j].push_back(i);
//超大常数的线段树qwq
#include<bits/stdc++.h>
using namespace std;
const int maxn=100005;
struct SegTree{
	int l,r;
	long long sum,tag;
	#define l(x) tree[x].l
	#define r(x) tree[x].r
	#define sum(x) tree[x].sum
	#define tag(x) tree[x].tag
}tree[maxn<<2];

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

void build(int p,int l,int r)
{
	l(p)=l, r(p)=r;
	if(l==r) {sum(p)=a[l];return;}
	int mid=(l+r)>>1; build(p<<1,l,mid),build(p<<1|1,mid+1,r);
	sum(p)=sum(p<<1)+sum(p<<1|1);
}

void pushdown(int p)
{
	if(tag(p)) {
		sum(p<<1)+=tag(p)*(r(p<<1)-l(p<<1)+1),sum(p<<1|1)+=tag(p)*(r(p<<1|1)-l(p<<1|1)+1);
		tag(p<<1)+=tag(p),tag(p<<1|1)+=tag(p);
		tag(p)=0;
	}
}

void chan(int p,int l,int r,long long k) {
	if(l<=l(p)&&r>=r(p)) {sum(p)+=k*(r(p)-l(p)+1);tag(p)+=k;return;}
	pushdown(p);
	int mid=(l(p)+r(p))>>1;
	if(l<=mid) chan(p<<1,l,r,k);
	if(r>mid) chan(p<<1|1,l,r,k);
	sum(p)=sum(p<<1)+sum(p<<1|1);
}

long long ask(int p,int l,int r) {
	if(l<=l(p)&&r>=r(p)) {return sum(p);}
	pushdown(p);
	int mid=(l(p)+r(p))>>1;
	long long val=0;
	val = (l<=mid) ? val+ask(p<<1,l,r) : val;
	val = (r>mid) ? val+=ask(p<<1|1,l,r) : val;
	return val;
}

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i) scanf("%lld",&a[i]);
	build(1,1,n);
	while(m--) {
		int op,l,r;
		scanf("%d%d%d",&op,&l,&r);
		if(op==1) {
			long long k;scanf("%lld",&k);
			chan(1,l,r,k);
		}
		else {
			cout<<ask(1,l,r)<<'
';
		}
	}
	return 0;
}
//扫描线求矩形面积
//maxn*2 line
//maxn*2 row
//maxn*8 c
#include<bits/stdc++.h>
using namespace std;
const int maxn=100005;
int n;
struct line{
	int x,yup,ydown,val;
}lines[maxn<<2];
int linecnt;
//lines
int pre[maxn<<2],precnt,row[maxn<<2],Cnt;
//row
long long ans=0;
void solve();

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;++i) {
		int xleft,xright,yup,ydown;
		scanf("%d%d%d%d",&xleft,&ydown,&xright,&yup);
		lines[++linecnt]=(line){xleft,yup,ydown,1};
		lines[++linecnt]=(line){xright,yup,ydown,-1};
		pre[++precnt]=yup;
		pre[++precnt]=ydown;
	}
	sort(pre+1,pre+precnt+1); pre[0]=-1;
	for(int i=1;i<=precnt;++i)
		if(pre[i]!=pre[i-1])
		row[++Cnt]=pre[i];
	for(int i=1;i<=linecnt;++i)
		lines[i].yup=lower_bound(row+1,row+1+Cnt,lines[i].yup)-row,
		lines[i].ydown=lower_bound(row+1,row+1+Cnt,lines[i].ydown)-row;
	solve();
	return 0;
}

struct SegTree {
	int l,r;
	int cnt,len;
	#define l(x) tree[x].l
	#define r(x) tree[x].r
	#define cnt(x) tree[x].cnt
	#define len(x) tree[x].len
}tree[maxn<<4];

void build(int p,int l,int r)
{
	l(p)=l, r(p)=r;
	if(l==r) return;
	int mid=(l+r)>>1;
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);
}

inline void pushup(int p)
{
	if(cnt(p)) len(p)=row[r(p)+1]-row[l(p)];
	else len(p)=len(p<<1)+len(p<<1|1);
}

void ins(int p,int l,int r,int val)
{
	if(l<=l(p)&&r>=r(p)) {cnt(p)+=val;pushup(p);return;}
	int mid=(l(p)+r(p))>>1;
	if(l<=mid) ins(p<<1,l,r,val);
	if(r>mid) ins(p<<1|1,l,r,val);
	pushup(p);
}

bool cmp(line a,line b)
{
    return a.x<b.x;
}

void solve() {
	build(1,1,Cnt-1);
    sort(lines+1,lines+1+linecnt,cmp);
	for(int i=1;i<=linecnt;++i) {
		ans+=(long long)len(1)*(lines[i].x-lines[i-1].x);
		ins(1,lines[i].ydown,lines[i].yup-1,lines[i].val);
	}
	cout<<ans;
	return;
}
//动态开点线段树
struct SegTree {
	int lc,rc;
	int dat;
}tr[size*2];
int root,tot;

int build() {
	tot++;
	tr[tot].dat=tr[tot].lc=tr[tot].rc=0;
	return tot;
}

void ins(int p,int l,int r,int val,int delta)
{
	if(l==r) {
		tr[p].dat+=delta;
		return;
	}
	int mid=(l+r)>>1;
	if(val<=mid) {
		if(!tr[p].lc) tr[p].lc-build();
		ins(tr[p].lc,l,mid,val,delta);
	}
	else {
		if(!tr[p].rc) tr[p].rc=build();
		ins(tr[p].rc,mid+1,r,val,delta);
	}
	tr[p].dat=max(tr[tr[p].lc].dat,tr[tr[p].rc].dat);
}

ins(root,1,n,val,delta);
//将以q为根的线段树合并到以p为根的线段树上 
int merge(int p,int q,int l,int r)
{
	if(!p||!q) return p+q;
	if(l==r) {
		tr[p].dat+=tr[q].dat;
		return p;
	}
	int mid=(l+r)>>1;
	tr[p].lc=merge(tr[p].lc,tr[q].lc,l,mid);
	tr[p].rc=merge(tr[p].rc,tr[q].rc,mid+1,r);
	tr[p].dat=max(tr[tr[p].lc].dat,tr[tr[p].rc].dat);
	return p;
}
//普通平衡树,树状数组写法(离线)
#include<bits/stdc++.h>
using namespace std;
const int maxn=100005;
int n;
int opt[maxn],x[maxn];
int row[maxn],cnt;
int t[maxn];

void ins(int x) {
	for(int i=x;i<=cnt;i+=i&-i) ++t[i];
}

void del(int x) {
	for(int i=x;i<=cnt;i+=i&-i) --t[i];
}

int que(int x) {
	int ret=0;
	for(int i=x;i>=1;i-=i&-i) ret+=t[i];
	return ret;
}

int kth(int k) {
	int ans=0,sum=0;
	for(int i=log2(cnt)+1;~i;--i) {
		if(ans+(1<<i)<=cnt&&sum+t[ans+(1<<i)]<k)
			sum+=t[ans+(1<<i)], ans+=1<<i;
	}
	return ans+1;
}

int main() {
	scanf("%d",&n);
	for(int i=1;i<=n;++i) {
		scanf("%d%d",&opt[i],&x[i]);
		if(opt[i]!=4) row[++cnt]=x[i];
	}
	sort(row+1,row+cnt+1);
	cnt=unique(row+1,row+cnt+1)-row-1;
	for(int i=1;i<=n;++i) {
		if(opt[i]!=4) x[i]=lower_bound(row+1,row+1+cnt,x[i])-row;
		switch(opt[i]) {
			case 1:
				ins(x[i]);
				break;
			case 2:
				del(x[i]);
				break;
			case 3:
				cout<<que(x[i]-1)+1<<'
';
				break;
			case 4:
				cout<<row[kth(x[i])]<<'
';
				break;
			case 5:
				cout<<row[kth(que(x[i]-1))]<<'
';
				break;
			case 6:
				cout<<row[kth(que(x[i])+1)]<<'
';
				break;
		}
	}
	return 0;
}

常见dfs剪枝思路:改变搜索顺序(显然)、可行性剪枝(显然)、最优性剪枝(显然)(左边都是常规操作)、排除等效冗余(不是很显然,在写出朴素程序后可以考虑)、动态规划(有点不显然,朴素程序可以考虑用来拍数据了)

十分适用迭代加深搜索的情境:答案所在深度比较有限(条件1),搜索树的层级规模会出现指数爆炸之类的现象(条件2)。

剪枝的一个最重要的应用前提是不影响最优答案的获取,其次是收益多少(如果剪枝所消耗的资源大于减掉的搜索子树规模消耗的资源总和……无限遐想……)

//hzwer数列动态分块入门系列

//1
#include <bits/stdc++.h>
using namespace std;

const int maxn = 50001;

int n, a[maxn];
int block, pos[maxn], add[maxn];
void init() {
    block = sqrt(n);
    for (int i = 1; i <= n; ++i) pos[i] = (i - 1) / block + 1;
}

void Add(int l, int r, int c) {
    if (pos[l] == pos[r]) {
        for (int i = l; i <= r; ++i) a[i] += c;
        return;
    }
    for (int i = pos[l] + 1; i <= pos[r] - 1; ++i) add[i] += c;
    for (int i = l; i <= pos[l] * block; ++i) a[i] += c;
    for (int i = (pos[r] - 1) * block + 1; i <= r; ++i) a[i] += c;
}

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
    init();
    for (int i = 1; i <= n; ++i) {
        int opt, l, r, c;
        scanf("%d%d%d%d", &opt, &l, &r, &c);
        if (opt == 0)
            Add(l, r, c);
        else
            cout << a[r] + add[pos[r]] << '
';
    }
    return 0;
}

//2

#include<bits/stdc++.h>
using namespace std;
const int maxn=50005;

int a[maxn], n;
int b[maxn];
int add[maxn], pos[maxn], L[maxn], R[maxn];

void init() {
	int t=sqrt(n);
	int block=n/t;
	for(int i=1;i<=t;++i) L[i]=(i-1)*block+1,R[i]=i*block;
	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;
		sort(b+L[i],b+R[i]+1);
	}
}

void Add(int l,int r,int c) {
	if(pos[l]==pos[r]) {
		for(int i=l;i<=r;++i) a[i]+=c;
		for(int i=L[pos[l]];i<=R[pos[l]];++i) b[i]=a[i];
		sort(b+L[pos[l]],b+R[pos[l]]+1);
		return;
	}
	for(int i=l;i<=R[pos[l]];++i) a[i]+=c;
	for(int i=L[pos[r]];i<=r;++i) a[i]+=c;
	for(int i=L[pos[l]];i<=R[pos[l]];++i) b[i]=a[i];
	for(int i=L[pos[r]];i<=R[pos[r]];++i) b[i]=a[i];
	sort(b+L[pos[l]],b+R[pos[l]]+1);
	sort(b+L[pos[r]],b+R[pos[r]]+1);
	for(int i=pos[l]+1;i<=pos[r]-1;++i) add[i]+=c;
}

int LB(int l, int r, int tmp) {
    int L = l, R = r;
    while (L < R) {
        int mid = (L + R + 1) >> 1;
        if (b[mid] >= tmp)
            R = mid - 1;
        else
            L = mid;
    }
    if (b[L] >= tmp)
        return 0;
    return L - l + 1;
}

int Que(int l, int r, int c) {
    int ret = 0;
    if (pos[l] == pos[r]) {
        for (int i = l; i <= r; ++i)
            if (c > a[i] + add[pos[i]])
                ++ret;
        return ret;
    }
    for (int i = l; i <= R[pos[l]]; ++i)
        if (c > a[i] + add[pos[i]])
            ++ret;
    for (int i = L[pos[r]]; i <= r; ++i)
        if (c > a[i] + add[pos[i]])
            ++ret;
    for (int i = pos[l] + 1; i <= pos[r] - 1; ++i) ret += LB(L[i], R[i], c - add[i]);
    return ret;
}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;++i) scanf("%d",&a[i]), b[i]=a[i];
	init();
	int opt,l,r,c;
	for(int i=1;i<=n;++i) {
		scanf("%d%d%d%d",&opt,&l,&r,&c);
		if(opt==0) Add(l,r,c);
		else cout<<Que(l,r,c*c)<<'
';
	}
	return 0;
}


//k短路
#include<bits/stdc++.h>
using namespace std;
const int maxn=1005;
const int maxm=100005;

int n,m;
int ct,ver[maxm],val[maxm],hed[maxm],nxt[maxm];//正图
int uct,uver[maxm],uval[maxm],uhed[maxm],unxt[maxm];//反图

int s,t,k;

void add(int a,int b,int c)
{
    ver[++ct]=b, val[ct]=c;
    nxt[ct]=hed[a],hed[a]=ct;
}
void uadd(int a,int b,int c)
{
    uver[++uct]=b, uval[uct]=c;
    unxt[uct]=uhed[a], uhed[a]=uct;
}

int f[maxn], vis[maxn];
struct Heapnode{
    int dist,u;
};
bool operator<(Heapnode a,Heapnode b)
{
    return !(a.dist<b.dist);
}
void Dij(int s)
{
    memset(f,0x3f,sizeof f); f[s]=0;
    priority_queue<Heapnode>Q;
    Q.push((Heapnode){0,s});
    while(!Q.empty())
    {
        int u=Q.top().u; Q.pop();
        if(vis[u]) continue; else vis[u]=true;
        for(int i=uhed[u];i;i=unxt[i]) {
            int v=uver[i];
            if(f[v]>f[u]+uval[i]) {
                f[v]=f[u]+uval[i];
                Q.push((Heapnode){f[v],v});
            }
        }
    }
}

void A_star(int s)
{
    int cnt[maxn]={0};
    priority_queue<Heapnode>q;
    q.push((Heapnode){f[s],s});
    while(!q.empty()) {
        int u=q.top().u, dis=q.top().dist-f[u]; q.pop();
        ++cnt[u];
        if(cnt[t]==k) {
            cout<<dis;
            return;
        }
        for(int i=hed[u];i;i=nxt[i]) {
            int v=ver[i];
            q.push((Heapnode){dis+val[i]+f[v],v});
        }
    }
    cout<<-1;
    return;
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;++i) {
        int a,b,c; scanf("%d%d%d",&a,&b,&c);
        add(a,b,c); uadd(b,a,c);
    }
    scanf("%d%d%d",&s,&t,&k);
    if(s==t) ++k;
    Dij(t);
    A_star(s);
    return 0;
}

既然普通BST在随机数据下的期望树高为log2n(n为节点数目),那么为什么不给每个节点random一个值,从而避免退化呢?

如果按此做法,则原本节点的值在BST中的相对位置就不满足BST性质了,此时BST就废了

最基础的平衡BST只需要满足两个要求:1.满足BST性质 2.树高不退化

平衡树的基本理论:用同一组值构造的BST不唯一

单旋与双旋是否能够保证BST的BST性质在旋转之后依旧满足呢?
由于双旋操作的子操作是单旋,所以只讨论单旋的BST不变性。

讨论右旋的情境。
设右旋操作将节点y的左子节点x旋到y的位置上,
y的右子树为C,x的左子树为A,x的右子树为B。
假设右旋之前,整棵树满足BST性质。

众所周知,BST性质被描述为:任意节点的键值都大于等于其左子树中任意节点的键值,且小于等于其右子树中任意节点的键值。
单旋转操作改变的是有限个节点的父子关系,可能能破坏BST性质的变化只有节点的子节点的改变。

在绕y的右旋中,子节点改变的只有三个节点:
y
x
y的父节点fa(y)

x的右子节点变为y,显然以x为根的子树满足BST性质
y的左子节点变为B,显然以y为根的子树满足BST性质
fa(y)的左子节点变为x,显然以fa(y)为根的子树满足BST性质

显然子节点未改变的各子树依然满足BST性质。
所以若右旋操作前BST满足BST性质,则右旋之后BST依然满足BST性质。
左旋转操作类似。
//背板子,效果很显著,在打代码的同时想象旋转操作的情境,十分有利于信道容量的拓宽(4G转5G OwO
void zig(int &p) {
	int q=a[p].l;
	a[p].l=a[q].r, a[q].r=p;
	p=q;
}
void zig(int &p) {
	int q=a[p].l;
	a[p].l=a[q].r, a[q].r=p;
	p=q;
}
void zig(int &p) {
	int q=a[p].l;
	a[p].l=a[q].r,a[q].r=p;
	p=q;
}
void zig(itn &p) {
	int q=a[p].l;
	a[p].l=a[q].r, a[q].r=p;
	p=q;
}
void zig(int &p) {
	int q=a[p].l;
	a[p].l=a[q].r, a[q].r=p;
	p=q;
}
void zig(int &p) {
	int q=a[p].l;
	a[p].l=a[q].r,a[q].r=p;
	p=q;
}
void zag(int &p) {
	int q=a[p].r;
	a[p].r=a[q].l, a[q].l=p;
	p=q;
}
void zag(int &p) {
	int q=a[p].r;
	a[p].r=a[p].l,a[q].l=p;
	p=q;
}
void zag(int &p) {
	int q=a[p].r;
	a[p].r=a[q].l,a[q].l=p;
	p=q;
}
void zag(int &p) {
	int q=a[p].r;
	q[p].r=a[q].l, a[q].l=p;
	p=q;
}
void zag(int &p)  {
	int q=a[p].r;
	a[p].r=a[q].l, a[q].l=p;
	p=q;
}
void zag(int &p) {
	int q=a[p].r;
	a[p].r=a[q].l,a[q].l=p;
	p=q;
}

void zig(int &p) {
	int q=a[p].l;
	a[p].l=a[q].r, a[q].r=p;
	p=q;
}

void zag(int &p) {
	int q=a[p].r;
	a[p].r=a[q].l, a[q].l=p;
	p=q;
}
void zig(int &p) {
	int q=a[p].l;
	a[p].l=a[q].r, a[q].r=p;
	p=q;
}
void zig(int &p) {
	int q=a[p].l;
	a[p].l=a[q].r, a[q].r=p;
	p=q;
}
void zig(int &p) {
	int q=a[p].l;
	a[p].l=a[q].r, a[q].r=p;
	p=q;
}
void zig(int &p) {
	int q=a[p].l;
	a[p].l=a[q].r, a[q].r=p;
	p=q;
}
void zig(int &p) {
	int q=a[p].l;
	a[p].l=a[q].r, a[q].r=p;
	p=q;
}
void zag(int &p) {
	int q=a[p].r;
	a[p].r=a[q].l, a[q].l=p;
	p=q;
}
void zag(int &p) {
	int q=a[p].r;
	a[p].r=a[q].l, a[q].l=p;
	p=q;
}
void zag(int &p) {
	int q=q[p].r;
	a[p].r=a[q].l, a[q].l=p;
	p=q;
}
void zag(int &p) {
	int q=a[p].r;
	a[p].r=a[q].l, a[q].l=p;
	p=q;
}
void zag(int &p) {
	int q=a[p].r;
	a[p].r=a[q].l, a[q].l=p;
	p=q;
}

//sb散列题
char s[1000010];
unsigned long long f[1000010], p[1000010];
int main() {
	scanf("%s",s+1);
	int n=strlen(s+1), q;cin>>q;
	p[0]=1;
	for(int i=1;i<=n;++i) {
		f[i]=f[i-1]*131+s[i]-'a'+1;
		p[i]=p[i-1]*131;
	}
	for(int i=1;i<=q;++i) {
		int l1,r1,l2,r2;
		scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
		if(f[r1]-f[l1-1]*p[r1-l1+1] == 
		   f[r2]-f[l2-1]*p[r2-l2+1]) {
		   	puts("Yes");
		}
		else {
			puts("No");
		}
	}
	return 0;
}

一般来说做矩阵快速幂的题时只需要四个矩阵和两个函数

原文地址:https://www.cnblogs.com/tztqwq/p/11641335.html