zoukankan      html  css  js  c++  java
  • XIII Open Cup named after E.V. Pankratiev. GP of Asia and South Caucasus

    A. RPG

    首先计算出每个技能对于每个属性值的可行区间,若区间为空则不合法。

    枚举两个技能,以及每个属性值,根据区间的关系可以得到哪个必须要在另一个之前学,连边看看是否有环即可。

    时间复杂度$O(n^2m)$。

    #include<stdio.h>
    #include<algorithm>
    #include<math.h>
    #include<string.h>
    #include<string>
    #include<vector>
    #include<set>
    #include<map>
    #include<queue>
    #include<time.h>
    #include<assert.h>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int>pi;
    const int Inf=1e9;
    int l[555][555],r[555][555];
    vector<int>G[555];
    int cnt[555];
    int n,m;
    bool topo(){
    	queue<int>q;
    	int tot=0;
    	for(int i=1;i<=n;i++){
    		if(!cnt[i])q.push(i);
    	}
    	while(!q.empty()){
    		int u=q.front();q.pop();tot++;
    		for(int i=0;i<G[u].size();i++){
    			int v=G[u][i];
    			cnt[v]--;
    			if(!cnt[v])q.push(v);
    		}
    	}
    	if(tot<n)return 0;
    	return 1;
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)l[i][j]=0,r[i][j]=Inf;
    	for(int i=1;i<=n;i++){
    		int k;scanf("%d",&k);
    		for(int j=0;j<k;j++){
    			char s[4];
    			int id,val,ty=0;
    			scanf("%d%s%d",&id,s,&val);
    			if(s[0]=='>')l[i][id]=max(l[i][id],val);
    			else r[i][id]=min(r[i][id],val);	
    		}
    	}
    	bool flag=1;
    	for(int i=1;i<=n&&flag;i++){
    		for(int j=1;j<=n&&flag;j++){
    			bool ned=0;;
    			for(int k=1;k<=m;k++){
    				if(l[i][k]>r[i][k]){flag=0;break;}
    				if(r[i][k]<l[j][k]){ned=1;break;}
    			}
    			if(i==j)continue;
    			if(ned){
    				//printf("i=%d j=%d
    ",i,j);
    				G[i].push_back(j),cnt[j]++;
    			}
    		}
    	}
    	if(flag&&!topo())flag=0;
    	puts(flag?"Yes":"No");
    	return 0;
    }
    

      

    B. Integer in integer

    按KMP的next数组进行数位DP即可,时间复杂度$O(|B||C|)$。

    #include<stdio.h>
    #include<algorithm>
    #include<math.h>
    #include<string.h>
    #include<string>
    #include<vector>
    #include<set>
    #include<map>
    #include<queue>
    #include<time.h>
    #include<assert.h>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int>pi;
    const int mod=1e9+7;
    char A[10020],B[10020],C[10020];
    int num[10020];
    int dp2[10020][2][2][502];
    int dp1[10020][2];
    int lsc;
    int to[10020][10];
    int f[555];
    inline void up(int &x,int y){x+=y;if(x>=mod)x-=mod;}
    int dfs1(int cur,int can){
    	if(cur<0)return 1;
    	int &t=dp1[cur][can];
    	if(t>=0)return t;
    	t=0;
    	for(int i=0;i<10;i++){
    		if(!can&&i>num[cur])break;
    		int ncan=can||(i<num[cur]);
    		up(t,dfs1(cur-1,ncan));
    	}
    	return t;
    }
    int dfs2(int cur,int qd,int can,int pp){
    	if(cur<0)return 0;
    	int &t=dp2[cur][qd][can][pp];
    	if(t>=0)return t;
    	t=0;
    	for(int i=0;i<10;i++){
    		if(!can&&i>num[cur])break;
    		int ncan=can||(i<num[cur]);
    		int nqd=qd||(i);
    		int npp=to[pp][i];
    		if(!nqd)npp=0;
    		if(npp>=lsc){
    			//printf("cur=%d pp=%d can=%d t0=%d
    ",cur,can,pp,t);
    			up(t,dfs1(cur-1,ncan));
    			//printf("cur=%d pp=%d can=%d t0=%d
    ",cur,can,pp,t);
    			up(t,dfs2(cur-1,nqd,ncan,f[lsc]));
    		}
    		else{
    			up(t,dfs2(cur-1,nqd,ncan,npp));
    		}
    	}
    	//if(t&&cur<=2)printf("%d %d %d t=%d
    ",cur,can,pp,t);
    	return t;
    }
    int solve(char *A){
    	int ls=strlen(A);
    	reverse(A,A+ls);
    	memset(num,0,sizeof num);
    	for(int i=0;i<ls;i++)num[i]=A[i]-'0';
    	memset(dp1,-1,sizeof dp1);
    	memset(dp2,-1,sizeof dp2);
    	//printf("",dfs1(0,));
    	int ret=dfs2(10000,0,0,0);
    	//printf("ret=%d
    ",ret);
    	return ret;
    }
    void getf(){
    	f[0]=f[1]=0;
    	for(int i=1;i<lsc;i++){
    		int j=f[i];
    		while(j&&(C[i]!=C[j]))j=f[j];
    		if(C[i]==C[j])f[i+1]=j+1;
    		else f[i+1]=0;
    	}
    	for(int i=0;i<lsc;i++){
    		for(int j=0;j<10;j++){
    			int t=i;
    			while(t&&((j+'0')!=C[t]))t=f[t];
    			if(C[t]==(j+'0'))to[i][j]=t+1;
    			else to[i][j]=0;
    		}
    	}
    }
    int main(){
    	scanf("%s%s%s",A,B,C);
    	lsc=strlen(C);
    	getf();
    	int ans=0;
    	for(int i=0,j=0;A[i];i++){
    		while(j&&A[i]!=C[j])j=f[j];
    		if(A[i]==C[j])j++;
    		else j=0;
    		if(j==lsc){j=f[lsc];ans++;}
    	}
    	//solve(A);
    	int ans1=solve(A);
    	int ans2=solve(B);
    	//printf("ans1=%d ans2=%d
    ",ans1,ans2);	
    	ans=((ans2-ans1+mod)%mod+ans)%mod;
    	printf("%d
    ",ans);
    	return 0;
    }
    

      

    C. Card Game

    留坑。

    D. Epidemy

    DLX重复覆盖,加上卡时即可通过。

    #include <bits/stdc++.h>
    using namespace std ;
    
    typedef long long LL ;
    
    #define rep( i , a , b ) for ( int i = ( a ) ; i <  ( b ) ; ++ i )
    #define For( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i )
    #define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )
    #define rec( i , A , o ) for ( int i = A[o] ; i != o ; i = A[i] )
    #define clr( a , x ) memset ( a , x , sizeof a )
    
    const int MAXN = 3005 ;
    const int MAXE = 30005 ;
    const int MAXNODE = 100005 ;
    const int INF = 0x3f3f3f3f ;
    
    struct DLX {
    	int L[MAXNODE] ;
    	int R[MAXNODE] ;
    	int D[MAXNODE] ;
    	int U[MAXNODE] ;
    	int row[MAXNODE] ;
    	int col[MAXNODE] ;
    	int H[MAXE] ;
    	int S[MAXE] ;
    	int n , k ;
    	int size ;
    	int vis[MAXE] , Time ;
    	int ans ;
    
    	void init ( int _n , int _k ) {
    		n = _n ;
    		k = _k ;
    		Time = 0 ;
    		clr ( H , -1 ) ;
    		clr ( vis , 0 ) ;
    		For ( i , 0 , n ) {
    			S[i] = 0 ;
    			U[i] = D[i] = i ;
    			L[i] = i - 1 ;
    			R[i] = i + 1 ;
    		}
    		L[0] = n ;
    		R[n] = 0 ;
    		size = n ;
    		ans = INF ;
    	}
    
    	void link ( int r , int c ) {
    		++ S[c] ;
    		++ size ;
    		row[size] = r ;
    		col[size] = c ;
    		D[size] = c ;
    		U[size] = U[c] ;
    		D[U[c]] = size ;
    		U[c] = size ;
    		if ( ~H[r] ) {
    			L[size] = L[H[r]] ;
    			R[size] = H[r] ;
    			R[L[size]] = size ;
    			L[R[size]] = size ;
    		} else L[size] = R[size] = H[r] = size ;
    	}
    
    	void remove ( int c ) {
    		rec ( i , D , c ) {
    			R[L[i]] = R[i] ;
    			L[R[i]] = L[i] ;
    		}
    	}
    
    	void resume ( int c ) {
    		rec ( i , U , c ) R[L[i]] = L[R[i]] = i ;
    	}
    
    	int h () {
    		++ Time ;
    		int cnt = 0 ;
    		rec ( i , R , 0 ) if ( vis[i] != Time ) {
    			vis[i] = Time ;
    			++ cnt ;
    			rec ( j , D , i ) rec ( k , R , j ) vis[col[k]] = Time ;
    		}
    		return cnt ;
    	}
    
    	void dance ( int d ) {
    		if ( clock () >= 2.5 * CLOCKS_PER_SEC ) return ;
    		if ( d + h () >= min ( ans , k + 1 ) ) return ;
    		//printf ( "dep = %d %d %d
    " , d , R[0] , ans ) ;
    		if ( !R[0] ) {
    			ans = min ( d , ans ) ;
    			return ;
    		}
    		int c = R[0] ;
    		rec ( i , R , 0 ) if ( S[i] < S[c] ) c = i ;
    		rec ( i , D , c ) {
    			remove ( i ) ;
    			rec ( j , R , i ) remove ( j ) ;
    			dance ( d + 1 ) ;
    			rec ( j , L , i ) resume ( j ) ;
    			resume ( i ) ;
    		}
    	}
    } ;
    
    DLX dlx ;
    vector < int > G[MAXN] ;
    int vis[MAXE] ;
    int deg[MAXN] ;
    int n , m , k ;
    
    void solve () {
    	dlx.init ( m , k ) ;
    	for ( int i = 1 ; i <= n ; ++ i ) {
    		G[i].clear () ;
    		deg[i] = 0 ;
    	}
    	for ( int i = 1 ; i <= m ; ++ i ) {
    		int u , v ;
    		scanf ( "%d%d" , &u , &v ) ;
    		G[u].push_back ( i ) ;
    		G[v].push_back ( i ) ;
    		++ deg[u] ;
    		++ deg[v] ;
    		vis[i] = 0 ;
    	}
    	int ans = 0 ;
    	for ( int i = 1 ; i <= n ; ++ i ) {
    		if ( deg[i] > k ) {
    			ans ++ ;
    			for ( int j = 0 ; j < G[i].size () ; ++ j ) {
    				vis[G[i][j]] = 1 ;
    			}
    		}
    	}
    	//printf ( "ans = %d
    " , ans ) ;
    	if ( ans > k ) {
    		printf ( "Impossible
    " ) ;
    		return ;
    	}
    	for ( int i = 1 ; i <= n ; ++ i ) {
    		if ( deg[i] <= k ) {
    			for ( int j = 0 ; j < G[i].size () ; ++ j ) {
    				if ( !vis[G[i][j]] ) {
    					//printf ( "link %d %d
    " , i , G[i][j] ) ;
    					dlx.link ( i , G[i][j] ) ;
    				}
    			}
    		}
    	}
    	for ( int i = 1 ; i <= m ; ++ i ) if ( vis[i] ) {
    		dlx.R[dlx.L[i]] = dlx.R[i] ;
    		dlx.L[dlx.R[i]] = dlx.L[i] ;
    	}
    	dlx.dance ( ans ) ;
    	if ( dlx.ans <= k ) printf ( "%d
    " , dlx.ans ) ;
    	else printf ( "Impossible
    " ) ;
    }
    
    int main () {
    	while ( ~scanf ( "%d%d%d" , &n , &m , &k ) ) solve () ;
    	return 0 ;
    }
    

      

    E. MST

    首先求出最小生成树,如果删掉的不是树边,那么答案不变,否则要找到一条经过它的权值最小的非树边来进行替换。

    按边权从小到大依次考虑每条非树边,那么就是一个树上染色问题,并查集维护即可。

    时间复杂度$O(mlog m)$。

    #include <bits/stdc++.h>
    using namespace std ;
    
    typedef long long LL ;
    typedef pair < int , int > pii ;
    
    #define clr( a , x ) memset ( a , x , sizeof a )
    #define cpy( a , x ) memcpy ( a , x , sizeof a )
    
    const int MAXN = 200005 ;
    const int MAXE = 400005 ;
    
    struct Edge {
    	int v , c , n ;
    	Edge () {}
    	Edge ( int v , int c , int n ) : v ( v ) , c ( c ) , n ( n ) {}
    } ;
    
    struct Node {
    	int u , v , c , id ;
    	bool operator < ( const Node& a ) const {
    		return c < a.c ;
    	}
    } ;
    
    Edge E[MAXE] ;
    Node a[MAXE] ;
    int H[MAXN] , cntE ;
    int pre[MAXN] ;
    int dep[MAXN] ;
    int val[MAXN] ;
    int in[MAXE] ;
    int be[MAXN] ;
    LL res[MAXN] ;
    int p[MAXN] ;
    int n , m ;
    
    void init () {
    	cntE = 0 ;
    	clr ( H , -1 ) ;
    }
    
    void addedge ( int u , int v , int c ) {
    	E[cntE] = Edge ( v , c , H[u] ) ;
    	H[u] = cntE ++ ;
    }
    
    void dfs ( int u , int f ) {
    	for ( int i = H[u] ; ~i ; i = E[i].n ) {
    		int v = E[i].v ;
    		if ( v == f ) continue ;
    		pre[v] = u ;
    		dep[v] = dep[u] + 1 ;
    		be[v] = E[i].c ;
    		dfs ( v , u ) ;
    	}
    }
    
    int F ( int x ) {
    	return p[x] == x ? x : ( p[x] = F ( p[x] ) ) ;
    }
    
    void solve () {
    	init () ;
    	for ( int i = 1 ; i <= n ; ++ i ) {
    		p[i] = i ;
    	}
    	for ( int i = 0 ; i < m ; ++ i ) {
    		scanf ( "%d%d%d" , &a[i].u , &a[i].v , &a[i].c ) ;
    		a[i].id = i ;
    		val[i] = -1 ;
    		in[i] = 0 ;
    	}
    	sort ( a , a + m ) ;
    	LL sum = 0 ;
    	int tot = n - 1 ;
    	for ( int i = 0 ; i < m ; ++ i ) {
    		int x = F ( a[i].u ) ;
    		int y = F ( a[i].v ) ;
    		if ( x != y ) {
    			-- tot ;
    			p[x] = y ;
    			in[i] = 1 ;
    			sum += a[i].c ;
    			addedge ( a[i].u , a[i].v , i ) ;
    			addedge ( a[i].v , a[i].u , i ) ;
    		}
    	}
    	if ( tot ) {
    		for ( int i = 0 ; i < m ; ++ i ) {
    			printf ( "-1
    " ) ;
    		}
    		return ;
    	}
    	for ( int i = 1 ; i <= n ; ++ i ) {
    		p[i] = i ;
    	}
    	dfs ( 1 , 1 ) ;
    	for ( int i = 0 ; i < m ; ++ i ) {
    		int u = a[i].u ;
    		int v = a[i].v ;
    		if ( !in[i] ) {
    			while ( 1 ) {
    				int x = F ( a[i].u ) ;
    				int y = F ( a[i].v ) ;
    				if ( x != y ) {
    					if ( dep[x] > dep[y] ) {
    						val[be[x]] = a[i].c ;
    						p[x] = F ( pre[x] ) ;
    						x = F ( pre[x] ) ;
    					} else {
    						val[be[y]] = a[i].c ;
    						p[y] = F ( pre[y] ) ;
    						y = F ( pre[y] ) ;
    					}
    				} else break ;
    			}
    		}
    	}
    	for ( int i = 0 ; i < m ; ++ i ) { 
    		if ( !in[i] ) {
    			res[a[i].id] = sum ;
    		} else {
    			if ( ~val[i] ) res[a[i].id] = sum - a[i].c + val[i] ;
    			else res[a[i].id] = -1 ;
    		}
    	}
    	for ( int i = 0 ; i < m ; ++ i ) {
    		printf ( "%lld
    " , res[i] ) ;
    	}
    }
    
    int main () {
    	while ( ~scanf ( "%d%d" , &n , &m ) ) solve () ;
    	return 0 ;
    }
    

      

    F. Molecules

    将每行倍长,然后依次拼接起来,得到一个序列,构造多项式FFT即可。

    时间复杂度$O(n^2log n)$。

    #include <stdio.h>
    #include <string.h>
    #include <math.h>
    #include <algorithm>
    using namespace std ;
    
    typedef long long LL ;
    
    #define clr( a , x ) memset ( a , x , sizeof a )
    #define cpy( a , x ) memcpy ( a , x , sizeof a )
    
    const int MAXN = 1030 ;
    const int MAXM = 1030 * 1030 * 4 ;
    const double pi = acos ( -1.0 ) ;
    
    struct Complex {
    	double r , i ;
    	Complex () {}
    	Complex ( double r , double i ) : r ( r ) , i ( i ) {}
    	Complex operator + ( const Complex& t ) const {
    		return Complex ( r + t.r , i + t.i ) ;
    	}
    	Complex operator - ( const Complex& t ) const {
    		return Complex ( r - t.r , i - t.i ) ;
    	}
    	Complex operator * ( const Complex& t ) const {
    		return Complex ( r * t.r - i * t.i , r * t.i + i * t.r ) ;
    	}
    } ;
    
    int n , m ;
    Complex x1[MAXM] , x2[MAXM] ;
    LL num[MAXM] ;
    LL ans[MAXM] ;
    
    
    void FFT ( Complex y[] , int n , int rev ) {
    	for ( int i = 1 , j , k , t ; i < n ; ++ i ) {
    		for ( j = 0 , k = n >> 1 , t = i ; k ; k >>= 1 , t >>= 1 ) {
    			j = j << 1 | t & 1 ;
    		}
    		if ( i < j ) swap ( y[i] , y[j] ) ;
    	}
    	for ( int s = 2 , ds = 1 ; s <= n ; ds = s , s <<= 1 ) {
    		Complex wn ( cos ( rev * 2 * pi / s ) , sin ( rev * 2 * pi / s ) ) ;
    		for ( int k = 0 ; k < n ; k += s ) {
    			Complex w ( 1 , 0 ) , t ;
    			for ( int i = k ; i < k + ds ; ++ i , w = w * wn ) {
    				y[i + ds] = y[i] - ( t = w * y[i + ds] ) ;
    				y[i] = y[i] + t ;
    			}
    		}
    	}
    	if ( rev < 0 ) {
    		for ( int i = 0 ; i < n ; ++ i ) {
    			y[i].r /= n ;
    		}
    	}
    }
    
    int dist ( int x , int y ) {
    	return x * x + y * y ;
    }
    
    void solve () {
    	LL tot = 0 ;
    	double ave = 0 ;
    	int x , n1 = 1 ;
    	clr ( num , 0 ) ;
    	clr ( ans , 0 ) ;
    	m = 2 * n * n ;
    	while ( n1 < 2 * m ) n1 <<= 1 ;
    	for ( int i = 0 ; i < n ; ++ i ) {
    		for ( int j = 0 ; j < n ; ++ j ) {
    			scanf ( "%d" , &x ) ;
    			num[i * 2 * n + j] = x ;
    			tot += x ;
    			ans[0] += x * ( x - 1 ) / 2 ;
    		}
    	}
    	/*for ( int i = 0 ; i < m ; ++ i ) {
    		printf ( "%d " , num[i] ) ;
    	}
    	printf ( "
    " ) ;*/
    	for ( int i = 0 ; i < m ; ++ i ) {
    		x1[i] = Complex ( num[i] , 0 ) ;
    		x2[i] = Complex ( num[m - i - 1] , 0 ) ;
    	}
    	for ( int i = m ; i < n1 ; ++ i ) {
    		x1[i] = x2[i] = Complex ( 0 , 0 ) ;
    	}
    	FFT ( x1 , n1 , 1 ) ;
    	FFT ( x2 , n1 , 1 ) ;
    	for ( int i = 0 ; i < n1 ; ++ i ) {
    		x1[i] = x1[i] * x2[i] ;
    	}
    	FFT ( x1 , n1 , -1 ) ;
    	/*for ( int i = 0 ; i < n1 ; ++ i ) {
    		printf ( "%d " , ( int ) ( x1[i].r + 0.5 ) ) ;
    	}
    	printf ( "
    " ) ;*/
    	for ( int i = m ; i < n1 ; ++ i ) {
    		num[i] = ( int ) ( x1[i].r + 0.5 ) ;
    		int x1 = 0 , y1 = 0 ;
    		int x2 = ( i - m + 1 ) / ( 2 * n ) ;
    		int y2 = ( i - m + 1 ) % ( 2 * n ) ;
    		if ( y2 >= n ) {
    			int tmp = n * 2 - y2 ;
    			y1 += tmp ;
    			x2 ++ ;
    			y2 = 0 ;
    		}
    		int dis = dist ( x1 - x2 , y1 - y2 ) ;
    		ans[dis] += num[i] ;
    		ave += sqrt ( 1.0 * dis ) * num[i] ;
    	}
    	tot = tot * ( tot - 1 ) / 2 ;
    	printf ( "%.10f
    " , ave / tot ) ;
    	int cnt = 0 ;
    	for ( int i = 0 ; i < MAXM ; ++ i ) if ( ans[i] ) {
    		printf ( "%d %lld
    " , i , ans[i] ) ;
    		++ cnt ;
    		if ( cnt >= 10000 ) break ;
    	}
    }
    
    int main () {
    	while ( ~scanf ( "%d" , &n ) ) solve () ;
    	return 0 ;
    }
    

      

    G. Carrier Pigeon

    http://blog.csdn.net/huyuncong/article/details/16861281

    #include<cstdio>
    const int N=100,inf=200000000;
    int n,m,S,T,F,o,i,j,k,t,x,e[1000][5],f[205][N][N],ans;
    inline void up(int&a,int b){if(a>b)a=b;}
    int main(){
      scanf("%d%d%d%d%d",&n,&m,&S,&T,&F);
      for(i=0;i<m;i++)for(j=0;j<5;j++)scanf("%d",&e[i][j]);
      for(o=1;o<=F;o++){
        for(i=0;i<n;i++)for(j=0;j<n;j++)if(i!=j)f[o][i][j]=inf;
        for(i=0;i<m;i++)if(e[i][2]>e[i][3]){
          if(o<=e[i][4])t=e[i][2]*o;else t=e[i][2]*e[i][4]+(o-e[i][4])*e[i][3];
          up(f[o][e[i][0]][e[i][1]],t);
        }
        for(k=0;k<n;k++)for(i=0;i<n;i++)for(j=0;j<n;j++)up(f[o][i][j],f[o][i][k]+f[o][k][j]);
      }
      ans=f[F][S][T];
      for(x=0;x<m;x++)if(e[x][2]<e[x][3])for(o=1;o<=F;o++){
        if(o<=e[x][4])t=e[x][2]*o;else t=e[x][2]*e[x][4]+(o-e[x][4])*e[x][3];
        for(i=0;i<n;i++)for(j=0;j<n;j++)up(ans,f[F][S][i]+f[o][i][e[x][0]]+t+f[o][e[x][1]][j]+f[F-o][i][j]+f[F][j][T]);
      }
      if(ans<inf)printf("%d",ans);else puts("Impossible");
      return 0;
    }
    

      

    H. Circles

    将第一个圆$10^6$等分,对于那些与第二个圆所在平面距离不超过$eps$的等分点,我们可以近似认为这些点就是第一个圆与第二个圆所在平面的交点,然后判断一下是否同时出现在第二个圆内和圆外的交点即可。

    #include<stdio.h>
    #include<algorithm>
    #include<math.h>
    #include<string.h>
    #include<string>
    #include<vector>
    #include<set>
    #include<map>
    #include<queue>
    #include<time.h>
    #include<assert.h>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    const double pi=acos(-1.0);
    
    const double EPS = 1e-4;
    const double eps=1e-4;
    struct Point3
    {
        double x,y,z;
        Point3() {}
        Point3(double x,double y,double z):x(x),y(y),z(z) {}
        void in(){
        	scanf("%lf%lf%lf",&x,&y,&z);
        }
        void pt(){
        	printf("x=%.3f y=%.3f z=%.3f
    ",x,y,z);
        }
    };
    
    typedef Point3 Vec3;
    
    Vec3 operator + (Vec3 A,Vec3 B)
    {
        return Vec3(A.x + B.x,A.y + B.y,A.z + B.z);
    }
    Vec3 operator - (Point3 A,Point3 B)
    {
        return Vec3(A.x-B.x,A.y-B.y,A.z-B.z);
    }
    Vec3 operator * (Vec3 A,double p)
    {
        return Vec3(A.x * p,A.y * p,A.z * p);
    }
    Vec3 operator / (Vec3 A,double p)
    {
        return Vec3(A.x / p,A.y / p,A.z / p);
    }
    
    int dcmp(double x)
    {
        return fabs(x) < EPS ? 0 : (x <0 ? -1:1);
    }
    
    double Dot3(Vec3 A, Vec3 B)
    {
        return A.x * B.x + A.y * B.y + A.z * B.z;
    }
    double Length3(Vec3 A)
    {
        return sqrt(Dot3(A,A));
    }
    double Angle(Vec3 A,Vec3 B)
    {
        return acos(Dot3(A,B) / Length3(A) / Length3(B));
    }
    Vec3 Cross3(Vec3 A,Vec3 B)
    {
        return Vec3(A.y * B.z - A.z * B.y,
                    A.z * B.x - A.x * B.z,
                    A.x * B.y - A.y * B.x);
    }
    double ssin,scos;
    Point3 rotate(Point3 a,Point3 b){//a
    	Point3 e1,e2,e3;
    	e3=b;double lens=Dot3(a,e3);
    	e1=a-e3*lens;
    	if(Length3(e1)>(1e-6)){e1=e1/Length3(e1);}else return a;
    	e2=Cross3(e1,e3);
    	double xx1=Dot3(a,e2),yy1=Dot3(a,e1),x=xx1*scos-yy1*ssin;
    	double y=xx1*ssin+yy1*scos;
    	return e3*lens+e1*y+e2*x;
    }
    struct Plane//平面:单位法向量+点
    {
        Vec3 n;
        Point3 p0;
        Plane() {}
        Plane(Vec3 nn,Point3 pp0)
        {
            n = nn/Length3(nn);
            p0 = pp0;
        }
        Plane(Point3 a,Point3 b,Point3 c)
        {
            Point3 nn = Cross3(b-a,c-a);
            n = nn/Length3(nn);
            p0 = a;
        }
    }yuan1,yuan2;
    Plane jpfPlane(Point3 a1,Point3 a2,Point3 b,Point3 c)//角平分面
    {
        Plane p1 = Plane(a1, b, c),p2 = Plane(a2,c,b);
        Vec3 temp = p1.n + p2.n;
        return Plane(Cross3(temp, c-b),b);
    }
    Point3 LinePlaneIntersection(Point3 p1,Point3 p2,Plane a)//线面交
    {
        Point3 p0 = a.p0;
        Vec3 n = a.n,v = p2-p1;
        double t = (Dot3(n,p0-p1) / Dot3(n,p2-p1));
        return p1 + v * t;
    }
    Point3 PlaneInsertion(Plane a,Plane b,Plane c)//三面交点
    {
        Vec3 nn = Cross3(a.n,b.n),use = Cross3(nn,a.n);
        Point3 st = LinePlaneIntersection(a.p0, a.p0+use,b);
        return LinePlaneIntersection(st, st+nn, c);
    }
    double DistanceToPlane(Point3 p,Plane a)//点到面的距离
    {
        Point3 p0 = a.p0;
        Vec3 n = a.n;
        return fabs(Dot3(p-p0,n)) / Length3(n);
    }
    bool isOnPlane(Point3 a,Point3 b,Point3 c,Point3 d)//判断是否四点共面
    {
        double t = Dot3(d-a,Cross3(b-a, c-a));
        return dcmp(t)==0;
    }
    bool check(Point3 pp,Plane pl){
    	//printf("dis=%.12f
    ",DistanceToPlane(pp,pl));
    	return fabs(DistanceToPlane(pp,pl))<eps;
    }
    bool solve(Point3 pp){
    	int LIM=1000000;
    	Point3 npp= yuan2.p0+pp;
    	int ret=0;
    	/*puts("faxiangliang");
    	yuan2.n.pt();
    	npp.pt();
    	*/
    	for(int i=0;i<LIM;i++){
    		//npp.pt();
    		//if(!check(npp,yuan2)){printf("i=%d
    ",i);puts("wa");}
    		if(check(npp,yuan1)){
    		//	npp.pt();
    			if(Length3(npp-yuan1.p0)<1-eps)ret|=1;
    			else ret|=2;
    		}
    		double angle=(i+0.0)/LIM*2*pi;
    		scos=cos(angle),ssin=sin(angle);
    		npp=rotate(pp,yuan2.n)+yuan2.p0;
    	}
    	return ret>=3;
    }
    int main(){
    	Point3 o;
    	Vec3 t1,t2;
    	o.in();
    	t1.in();t2.in();
    	yuan1=Plane(o,o+t1,o+t2);
    	o.in();
    	t1.in();t2.in();
    	yuan2=Plane(o,o+t1,o+t2);
    	if(solve(t1))puts("YES");else puts("NO");
    	return 0;
    }
    

      

    I. Queries

    整体二分,用扫描线求出某个区间内的点数即可。

    对于排序可以预先在一开始排好序,然后每次递归分治的时候保证不破坏顺序即可。

    时间复杂度$O((m+q)log m)$。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=100010,M=N<<1;
    int n,m,i,x,y,a[N],e[N][3],cb,cc,qb[M],qc[M],ql[M],qr[M],ans[N];ll f[N],g[N];
    struct E{int x,y,t;E(){}E(int _x,int _y,int _t){x=_x,y=_y,t=_t;}}b[M],c[M];
    inline bool cmp(const E&a,const E&b){return a.x<b.x;}
    inline int lower(int x){
      int l=1,r=n,mid,t;
      while(l<=r)if(a[mid=(l+r)>>1]<=x)l=(t=mid)+1;else r=mid-1;
      return t;
    }
    void solve(int l,int r,int bl,int br,int cl,int cr){
      if(bl>br||cl>cr)return;
      if(l==r){
        for(int i=cl;i<=cr;i++)ans[c[qc[i]].y]=a[l];
        return;
      }
      for(int i=cl;i<=cr;i++)g[c[qc[i]].y]=0;
      int mid=(l+r)>>1,c0=0,c1=0;ll s0=0,s1=0;
      for(int i=cl,j=bl;i<=cr;i++){
        for(;j<=br&&b[qb[j]].x<=c[qc[i]].x;j++){
          if(b[qb[j]].y>mid)continue;
          if(b[qb[j]].t>0)c0++,s0+=b[qb[j]].x;else c1++,s1+=b[qb[j]].x;
        }
        ll t=(1LL*(c[qc[i]].x+1)*c0-s0)-(1LL*(c[qc[i]].x+1)*c1-s1);
        if(c[qc[i]].t>0)g[c[qc[i]].y]+=t;else g[c[qc[i]].y]-=t;
      }
      int L=0,R=0;
      for(int i=bl;i<=br;i++)if(b[qb[i]].y<=mid)ql[L++]=qb[i];else qr[R++]=qb[i];
      for(int i=0;i<L;i++)qb[bl+i]=ql[i];
      for(int i=0;i<R;i++)qb[bl+L+i]=qr[i];
      int bm=bl+L-1;
      L=R=0;
      for(int i=cl;i<=cr;i++){
        int j=c[qc[i]].y;
        if(f[j]<=g[j])ql[L++]=qc[i];else qr[R++]=qc[i];
      }
      for(int i=cl;i<=cr;i++)if(c[qc[i]].t>0){
        int j=c[qc[i]].y;
        if(f[j]>g[j])f[j]-=g[j];
      }
      for(int i=0;i<L;i++)qc[cl+i]=ql[i];
      for(int i=0;i<R;i++)qc[cl+L+i]=qr[i];
      solve(l,mid,bl,bm,cl,cl+L-1),solve(mid+1,r,bm+1,br,cl+L,cr);
    }
    int main(){
      scanf("%d%d%d",&i,&n,&m);
      for(i=1;i<=n;i++){
        scanf("%d%d%d",&e[i][0],&e[i][1],&e[i][2]);
        a[i]=e[i][2];
      }
      sort(a+1,a+n+1);
      for(i=1;i<=n;i++){
        e[i][2]=lower(e[i][2]);
        b[++cb]=E(e[i][0],e[i][2],1);
        b[++cb]=E(e[i][1]+1,e[i][2],-1);
      }
      for(i=1;i<=m;i++){
        scanf("%d%d%lld",&x,&y,&f[i]);
        c[++cc]=E(x-1,i,-1);
        c[++cc]=E(y,i,1);
      }
      sort(b+1,b+cb+1,cmp);
      sort(c+1,c+cc+1,cmp);
      for(i=1;i<=cb;i++)qb[i]=i;
      for(i=1;i<=cc;i++)qc[i]=i;
      solve(1,n,1,cb,1,cc);
      for(i=1;i<=m;i++)printf("%d
    ",ans[i]);
      return 0;
    }
    

      

    J. Restoring the Flows

    设$x[i]$为第$i$条边的流量,对于每个节点根据流量平衡列出方程,那么一共有$m$个未知量,$n$个方程,答案就是这个矩阵的秩。

    注意到任意时刻每个未知量只出现两次,并且系数一正一负,因此直接高斯消元的复杂度为$O(nm)$。

    #include <bits/stdc++.h>
    using namespace std ;
    
    typedef long long LL ;
    typedef pair < int , int > pii ;
    
    #define clr( a , x ) memset ( a , x , sizeof a )
    #define cpy( a , x ) memcpy ( a , x , sizeof a )
    
    const int MAXN = 505 ;
    const int MAXM = 3005 ;
    
    int a[MAXN][MAXM] , n , m ;
    
    int gauss ( int n , int m ) {
    	int r = 1 , c = 1 ;
    	for ( ; r <= n && c <= m ; ) {
    		int tmp = r ;
    		for ( int i = r ; i <= n ; ++ i ) {
    			if ( a[i][c] ) tmp = i ;
    		}
    		if ( tmp == r ) {
    			++ c ;
    			continue ;
    		}
    		for ( int i = 1 ; i <= m ; ++ i ) {
    			swap ( a[r][i] , a[tmp][i] ) ;
    		}
    		for ( int i = r + 1 ; i <= n ; ++ i ) if ( a[i][c] ) {
    			for ( int j = c ; j <= m ; ++ j ) {
    				a[i][j] += a[r][j] ;
    			}
    		}
    		++ r ;
    	}
    	return m - r + 1 ;
    }
    
    void solve () {
    	for ( int i = 1 ; i <= n ; ++ i ) {
    		for ( int j = 1 ; j <= m ; ++ j ) {
    			a[i][j] = 0 ;
    		}
    	}
    	for ( int i = 1 ; i <= m ; ++ i ) {
    		int u , v ;
    		scanf ( "%d%d" , &u , &v ) ;
    		a[u][i] = 1 ;
    		a[v][i] = -1 ;
    	}
    	printf ( "%d
    " , gauss ( n , m ) ) ;
    }
    
    int main () {
    	while ( ~scanf ( "%d%d" , &n , &m ) ) solve () ;
    	return 0 ;
    }
    

      

  • 相关阅读:
    LLDB 常用的调试命令
    iOS https认证
    pod lib lint xxx.podspec 验证出错 Could not find a `ios` simulator
    LLDB 调试
    First throw call stack: 不打印方法名
    AOP
    增强现实
    2017
    iOS的主要框架介绍 (转载)
    iOS中都有什么设计模式?各个设计模式的作用 (转载)
  • 原文地址:https://www.cnblogs.com/clrs97/p/5931629.html
Copyright © 2011-2022 走看看