zoukankan      html  css  js  c++  java
  • 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;
    }
    

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

  • 相关阅读:
    Java基础50道经典练习题(23)——求岁数
    Java基础50道经典练习题(22)——递归求阶乘
    团队第一阶段冲刺04
    团队第一阶段冲刺03
    团队第一阶段冲刺02
    团队第一阶段冲刺01
    软件工作进度01
    软团队项目01之电梯演讲视频
    团队项目1
    C语言动静态链接库使用(笔记)
  • 原文地址:https://www.cnblogs.com/tztqwq/p/11641335.html
Copyright © 2011-2022 走看看