<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      XVIII Open Cup named after E.V. Pankratiev. Ukrainian Grand Prix

      A. Accommodation Plan

      對于已知的$K$個點,離它們距離都不超過$L$的點在樹上是一個連通塊,考慮在每種方案對應的離$1$最近的點統計。

      即對于每個點$x$,統計離它距離不超過$L$的點數$call[x]$,再減去離它和它父親距離都不超過$L$的點數$cext[x]$,然后用組合數計算方案數。

      對于$call[x]$可以通過點分治+排序雙指針$O(n\log^2n)$統計。

      對于$cext[x]$,注意到$cext[x]=call[x]-csub[x]$,其中$csub[x]$表示$x$點子樹中深度在$(dep[x]+L-dis(x,fa[x]),dep[x]+L]$的點數,二維數點問題,掃描線+樹狀數組維護即可$O(n\log n)$統計。

      時間復雜度$O(n\log^2n)$。

      #include<cstdio>
      #include<algorithm>
      using namespace std;
      typedef long long ll;
      const int N=100010,P=1000000007;
      int n,K,L,i,j,x,y,z,fac[N],inv[N],ans;
      int g[N],nxt[N<<1],v[N<<1],w[N<<1],ok[N<<1],ed,son[N],f[N],all,now;
      int call[N],csub[N],cnt,bit[N],st[N],en[N],dfn;
      struct E{ll x;int y;E(){}E(ll _x,int _y){x=_x,y=_y;}}e[N],q[N<<1];
      inline bool cmp(const E&a,const E&b){return a.x<b.x;}
      inline void add(int x,int y,int z){v[++ed]=y;w[ed]=z;nxt[ed]=g[x];g[x]=ed;ok[ed]=1;}
      void findroot(int x,int y){
        son[x]=1,f[x]=0;
        for(int i=g[x];i;i=nxt[i])if(v[i]!=y&&ok[i]){
          findroot(v[i],x);
          son[x]+=son[v[i]];
          if(son[v[i]]>f[x])f[x]=son[v[i]];
        }
        if(all-son[x]>f[x])f[x]=all-son[x];
        if(f[x]<f[now])now=x;
      }
      void dfs(int x,int y,ll z){
        e[++cnt]=E(z,x);
        for(int i=g[x];i;i=nxt[i])if(v[i]!=y&&ok[i])dfs(v[i],x,z+w[i]);
      }
      inline void cal(int p){
        sort(e+1,e+cnt+1,cmp);
        int i,j;
        for(i=1,j=cnt;i<=cnt;i++){
          while(j&&e[i].x+e[j].x>L)j--;
          call[e[i].y]+=p*j;
        }
      }
      void solve(int x){
        int i;
        cnt=0;
        dfs(x,0,0);
        cal(1);
        for(i=g[x];i;i=nxt[i])if(ok[i]){
          cnt=0;
          dfs(v[i],x,w[i]);
          cal(-1);
        }
        for(i=g[x];i;i=nxt[i])if(ok[i]){
          ok[i^1]=0;
          f[0]=all=son[v[i]];
          findroot(v[i],now=0);
          solve(now);
        }
      }
      void dfs2(int x,int y,ll z){
        st[x]=++dfn;
        e[x]=E(z,x);
        q[++cnt]=E(z+L,x);
        for(int i=g[x];i;i=nxt[i])if(v[i]!=y){
          q[++cnt]=E(z+L,-v[i]);
          dfs2(v[i],x,z+w[i]);
        }
        en[x]=dfn;
      }
      inline void ins(int x){for(;x<=n;x+=x&-x)bit[x]++;}
      inline int ask(int x){int t=0;for(;x;x-=x&-x)t+=bit[x];return t;}
      inline int C(int n,int m){return n<m?0:1LL*fac[n]*inv[m]%P*inv[n-m]%P;}
      int main(){
        scanf("%d%d%d",&n,&K,&L);
        for(ed=i=1;i<n;i++)scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,z);
        f[0]=all=n;findroot(1,now=0);solve(now);
        dfs2(1,cnt=0,0);
        sort(e+1,e+n+1,cmp);
        sort(q+1,q+cnt+1,cmp);
        for(i=j=1;i<=cnt;i++){
          while(j<=n&&e[j].x<=q[i].x)ins(st[e[j++].y]);
          x=q[i].y;
          if(x<0)x=-x;
          y=ask(en[x])-ask(st[x]-1);
          if(q[i].y>0)csub[x]+=y;else csub[x]-=y;
        }
        for(fac[0]=i=1;i<=n;i++)fac[i]=1LL*fac[i-1]*i%P;
        for(inv[0]=inv[1]=1,i=2;i<=n;i++)inv[i]=1LL*(P-inv[P%i])*(P/i)%P;
        for(i=2;i<=n;i++)inv[i]=1LL*inv[i-1]*inv[i]%P;
        for(i=1;i<=n;i++)ans=((ans+C(call[i],K))%P+P-C(call[i]-csub[i],K))%P;
        ans=1LL*ans*fac[K]%P;
        printf("%d",ans);
      }
      

        

      B. Card Game

      枚舉$n$的所有約數判斷。

      #include<stdio.h>
      #include<iostream>
      #include<string.h>
      #include<string>
      #include<ctype.h>
      #include<math.h>
      #include<set>
      #include<map>
      #include<vector>
      #include<queue>
      #include<bitset>
      #include<algorithm>
      #include<time.h>
      using namespace std;
      void fre() {  }
      #define MS(x, y) memset(x, y, sizeof(x))
      #define ls o<<1
      #define rs o<<1|1
      typedef long long LL;
      typedef unsigned long long UL;
      typedef unsigned int UI;
      template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
      template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
      const int N = 1e5 + 10, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;
      template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
      int casenum, casei;
      int n, m;
      int a[N];
      map<int, int> mop;
      
      int main()
      {
          while(~ scanf("%d%d", &n, &m)){
              mop.clear();
              int A = 0, B = 0;
              for(int i = 1; i <= m; i ++){
                  scanf("%d", &a[i]);
                  gmax(A, a[i]);
                  mop[a[i]] ++;
                  gmax(B, mop[a[i]]);
              }
              //printf("%d %d\n", A, B);
              int ans = 0;
              for(int i = 1; i * i <= n; i ++){
                  if(n % i == 0){
                      int j = n / i;
                      if(i >= A && j >= B){
                          ans ++;
                          //printf("i j %d %d\n", i, j);
                      }
                      if(i != j && i >= B && j >= A){
                          ans ++;
      
                          //printf("j i %d %d\n", j, i);
                      }
                  }
              }
              if(ans != 1) puts("NO");
              else puts("YES");
          }
      	return 0;
      }
      
      /*
      【trick&&吐槽】
      
      
      【題意】
      
      
      【分析】
      
      
      【時間復雜度&&優化】
      
      
      */
      

        

      C. The Most Expensive Gift

      若循環節長度為$1$,則答案下界為$\frac{n^2}{9}$,經過分析可得循環節長度超過$8$都是不優的。

      暴力搜索所有長度不超過$8$的串作為循環節,然后貪心匹配計算長度即可。

      時間復雜度$O(3^8n)$。

      #include<stdio.h>
      #include<iostream>
      #include<string.h>
      #include<string>
      #include<ctype.h>
      #include<math.h>
      #include<set>
      #include<map>
      #include<vector>
      #include<queue>
      #include<bitset>
      #include<algorithm>
      #include<time.h>
      using namespace std;
      void fre() {  }
      #define MS(x, y) memset(x, y, sizeof(x))
      #define ls o<<1
      #define rs o<<1|1
      typedef long long LL;
      typedef unsigned long long UL;
      typedef unsigned int UI;
      template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
      template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
      const int N = 10010, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;
      template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
      int casenum, casei;
      int n;
      char s[N];
      char a[N];
      int ans;
      int len;
      int check()
      {
      	int pos = 0;
      	int now = 0;
      	for(int i = 0; i < n; ++i)
      	{
      		if(s[i] == a[pos])
      		{
      			++now;
      			pos = pos + 1;
      			if(pos == len)pos = 0;
      		}
      	}
      	int LEN = now / len * len;
      	return LEN * LEN / len;
      }
      int main()
      {
      	while(~scanf("%d%s",&n, s))
      	{
      		ans = 0;
      		for(len = 1; ; ++len)
      		{
      			int bst = n * n / len;
      			if(bst <= ans)break;
      			
      			int top = 1;
      			for(int i = 0; i < len; ++i)
      			{
      				a[i] = 'a';
      				top *= 3;
      			}
      			for(int tim = 1; tim <= top; ++tim)
      			{
      				gmax(ans, check());
      				++a[len - 1];
      				int pos = len - 1;
      				while(a[pos] == 'd')
      				{
      					a[pos] = 'a';
      					++a[--pos];
      				}
      			}
      		}
      		printf("%d\n", ans);
      	}
      	return 0;
      }
      
      /*
      【trick&&吐槽】
      
      
      【題意】
      
      
      【分析】
      
      
      【時間復雜度&&優化】
      
      
      */
      

        

      D. Cut the Cake

      兩個維度獨立,對于一維問題,將所有位置排序,每隔$k$個切一刀即可。

      #include<cstdio>
      const int N=300;
      int n,m,k,i,j,dx,dy,cntx,cnty,cx[N],cy[N],qx[N],qy[N];char a[N][N];
      inline int cal(int xl,int xr,int yl,int yr){
      	int t=0;
      	for(int i=xl;i<=xr;i++)for(int j=yl;j<=yr;j++)if(a[i][j]=='1')t++;
      	return t;
      }
      int main(){
      	scanf("%d%d%d",&n,&m,&k);
      	for(i=1;i<=n;i++)scanf("%s",a[i]+1);
      	for(i=1;i<=n;i++)for(j=1;j<=m;j++)if(a[i][j]=='1'){
      		dx++;
      		if(dx%k==0&&dx<k*k)cx[i]=1;
      	}
      	for(j=1;j<=m;j++)for(i=1;i<=n;i++)if(a[i][j]=='1'){
      		dy++;
      		if(dy%k==0&&dy<k*k)cy[j]=1;
      	}
      	for(i=1;i<n;i++)if(cx[i])qx[++cntx]=i;
      	for(i=1;i<m;i++)if(cy[i])qy[++cnty]=i;
      	if(cntx!=k-1||cnty!=k-1)return puts("NO"),0;
      	qx[cntx+1]=n;
      	qy[cnty+1]=m;
      	for(i=1;i<=cntx;i++)for(j=1;j<=cnty;j++)if(cal(qx[i-1]+1,qx[i],qy[j-1]+1,qy[j])!=1)return puts("NO"),0;
      	puts("YES");
      	for(i=1;i<=cntx;i++)printf("%d ",qx[i]);puts("");
      	for(i=1;i<=cnty;i++)printf("%d ",qy[i]);puts("");
      }
      

        

      E. Message

      留坑。

       

      F. Bad Word

      若整個串不是回文串,則答案顯然為$1$。

      若整個串形如$aaaaa$、$aabaa$、$ababa$,則無解。

      否則答案必然是$2$。

      #include<cstdio>
      const int N=200010;
      int n,i;char a[N];
      int main(){
      	scanf("%d%s",&n,a+1);
      	for(i=1;i<=n;i++)if(a[i]!=a[n-i+1])break;
      	if(i<=n)return puts("1"),0;
      	for(i=1;i<=n;i++)if(a[i]!=a[1])break;
      	if(i>n)return puts("-1"),0;
      	if(n%2==0)return puts("2"),0;
      	for(i=1;i<=n/2;i++)if(a[i]!=a[1])break;
      	if(i>n/2)return puts("-1"),0;
      	for(i=1;i<=n;i++){
      		if(i>2&&a[i]!=a[i-2])break;
      	}
      	if(i>n)return puts("-1"),0;
      	puts("2");
      }
      

        

      G. Zenyk, Marichka and Interesting Game

      首先將所有石子數都模$A+B$,并剔除小于$\min(A,B)$的堆。

      若$A=B$,則根據奇偶性判斷即可。

      若$A>B$,枚舉$A$的第一步行動,然后交換先后手,轉化為$A<B$的問題。

      若$A<B$:

      • 若$n=0$,則先手必敗。
      • 若一步之內可以造出只能$A$拿的堆,即存在石子數$<B$或者$\geq 2A$的堆,那么$A$可以利用這一堆來控制先后手,從而必勝。
      • 否則任何一堆兩人都只能恰好拿一次,故根據$n$的奇偶性判斷即可。
      #include<cstdio>
      #include<set>
      #include<algorithm>
      using namespace std;
      typedef pair<int,int>P;
      const int N=100010;
      int n,m,A,B,x,a[N];set<P>T;
      int work(int A,int B){
      	if(T.size()==0)return 0;
      	set<P>::iterator x=T.begin();
      	if(x->first<B)return 1;
      	x=T.end();
      	x--;
      	if(x->first>=A*2)return 1;
      	return T.size()%2;
      }
      int solve(){
      	int i,ans=0;
      	if(A==B){
      		for(i=1;i<=m;i++)ans=(ans+a[i]/A)%2;
      		return ans;
      	}
      	if(A<B)return work(A,B);
      	for(i=1;i<=m;i++)if(a[i]>=A){
      		T.erase(P(a[i],i));
      		int t=a[i]-A;
      		if(t<A&&t<B)t=0;
      		if(t)T.insert(P(t,i));
      		if(!work(B,A))return 1;
      		if(t)T.erase(P(t,i));
      		T.insert(P(a[i],i));
      	}
      	return 0;
      }
      int main(){
      	scanf("%d%d%d",&n,&A,&B);
      	while(n--){
      		scanf("%d",&x);
      		x%=A+B;
      		if(x<A&&x<B)continue;
      		a[++m]=x;
      		T.insert(P(x,m));
      	}
      	puts(solve()?"Zenyk":"Marichka");
      }
      

        

      H. Frog Jumping

      貪心用代價最小的若干個青蛙去貪心地走路線。

      #include<stdio.h>
      #include<iostream>
      #include<string.h>
      #include<string>
      #include<ctype.h>
      #include<math.h>
      #include<set>
      #include<map>
      #include<vector>
      #include<queue>
      #include<bitset>
      #include<algorithm>
      #include<time.h>
      using namespace std;
      void fre() {  }
      #define MS(x, y) memset(x, y, sizeof(x))
      #define ls o<<1
      #define rs o<<1|1
      typedef long long LL;
      typedef unsigned long long UL;
      typedef unsigned int UI;
      template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
      template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
      const int N = 1e5 + 10, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;
      template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
      int casenum, casei;
      int n, m, K, D;
      int c[N];
      LL sum[N];
      int a[N];
      int main()
      {
      	while(~scanf("%d%d%d%d",&n, &m, &K, &D))
      	{
      		for(int i = 1; i <= m; ++i)scanf("%d", &c[i]);
      		sort(c + 1, c + m + 1);
      		for(int i = 1; i <= m; ++i)
      		{
      			sum[i] = sum[i - 1] + c[i];
      		}
      		set<int>sot;
      		for(int i = 1; i <= K; ++i)
      		{
      			scanf("%d", &a[i]);
      			sot.insert(a[i]);
      		}
      		sort(a + 1, a + K + 1);
      		int way = 0;
      		int pos = 1;
      		sot.insert(n);
      		while(!sot.empty())
      		{
      			auto it = sot.upper_bound(pos + D);
      			
      			//can't reach it
      			if(it == sot.begin())
      			{
      				break;
      			}
      			
      			--it;
      			pos = *it;
      			//
      			//printf("pos = %d\n", pos);
      			//
      			if(pos == n)
      			{
      				++way;
      				if(way >= m)break;
      				pos = 1;
      			}
      			else sot.erase(it);
      		}
      		//
      		//printf("Here: way = %d\n", way);
      		//
      		LL ans = 0;
      		if(way == 0)
      		{
      			a[0] = 1; a[K + 1] = n;
      			for(int i = 1; i <= K + 1; ++i)
      			{
      				int dis = a[i] - a[i - 1];
      				if(dis > D)
      				{
      					ans += c[1];
      				}
      			}
      			ans += sum[m] - sum[1];
      		}
      		else
      		{
      			ans = sum[m - way];
      		}
      		printf("%lld\n", ans);
      	}
      	return 0;
      }
      
      /*
      【trick&&吐槽】
      10 2 3 3
      4 7
      4 8 7
      
      10 2 2 3
      4 7
      9 5
      
      【題意】
      
      
      【分析】
      
      
      【時間復雜度&&優化】
      
      
      */
      

        

      I. Slot Machine

      按照最壞情況模擬即可。

      #include<stdio.h>
      #include<iostream>
      #include<string.h>
      #include<string>
      #include<ctype.h>
      #include<math.h>
      #include<set>
      #include<map>
      #include<vector>
      #include<queue>
      #include<bitset>
      #include<algorithm>
      #include<time.h>
      using namespace std;
      void fre() {  }
      #define MS(x, y) memset(x, y, sizeof(x))
      #define ls o<<1
      #define rs o<<1|1
      typedef long long LL;
      typedef unsigned long long UL;
      typedef unsigned int UI;
      template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
      template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
      const int N = 1e5 + 10, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;
      template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
      int casenum, casei;
      int n;
      vector<int>vt[N];
      int a[N];
      set< pair<int,int> >sot[N];
      int main()
      {
      	while(~scanf("%d",&n))
      	{
      		int ANS = inf;
      		for(int i = 0; i < N; ++i)sot[i].clear();
      		for(int i = 1; i <= n; ++i)
      		{
      			vt[i].clear();
      			int g;
      			scanf("%d", &g);
      			for(int j = 1; j <= g; ++j)
      			{
      				int x;
      				scanf("%d", &x);
      				vt[i].push_back(x);
      			}
      			sort(vt[i].begin(), vt[i].end());
      			int col = 0;
      			for(int j = 0; j < g; ++j)
      			{
      				if(j == g - 1 || vt[i][j] != vt[i][j + 1])
      				{
      					++col;
      				}
      			}
      			int cnt = 0;
      			for(int j = 0; j < g; ++j)
      			{
      				++cnt;
      				if(j == g - 1 || vt[i][j] != vt[i][j + 1])
      				{
      				    if(cnt > 1)gmin(ANS, col + 1);
      					sot[ vt[i][j] ].insert( {col, i} );
      					cnt = 0;
      				}
      			}
      		}
      		for(int i = 1; i <= n; ++i)
      		{
      			int g = vt[i].size();
      			int cnt = 0;
      			int col = 0;
      			for(int j = 0; j < g; ++j)
      			{
      				++cnt;
      				if(j == g - 1 || vt[i][j] != vt[i][j + 1])
      				{
      					a[++col] = inf;
      					for(auto it : sot[ vt[i][j] ])
      					{
      						int bl = it.second;
      						if(bl == i && cnt == 1)continue;
      						a[col] = it.first + 1;
      						break;
      					}
      					cnt = 0;
      				}
      			}
      			sort(a + 1, a + col + 1);
      			reverse(a + 1, a + col + 1);
      			for(int j = 1; j <= col; ++j)
      			{
      				//printf("(%d %d): %d\n", i, j, a[j]);
      				gmin(ANS, a[j] + j - 1);
      			}
      		}
      		printf("%d\n", ANS);
      	}
      	return 0;
      }
      
      /*
      【trick&&吐槽】
      7
      4 1 2 3 4
      1 1
      1 2
      1 3
      1 4
      7 4 7 4 4 7 7 4
      1 5
      
      
      5
      5 1 2 5 3 4
      5 1 2 5 6 7
      5 1 2 5 8 9
      5 1 2 5 10 11
      20 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
      
      2
      5 1 2 3 4 5
      1 1
      
      
      1
      5 1 2 3 1 2
      
      【題意】
      
      
      【分析】
      
      
      【時間復雜度&&優化】
      
      
      */
      

        

      J. Half is Good

      注意到邊權在$[0,2^{62})$內隨機,故最后$8$位影響排序結果的概率非常小,可以忽略。

      還剩$54$位,分成最高的$22$位和后面$32$位,將最高的$22$位相同的邊分組,每組內部排序,每組數量都不多。

      然后直接求最小生成樹即可。

      #include<cstdio>
      #include<algorithm>
      using namespace std;
      typedef unsigned int U;
      typedef unsigned long long ll;
      const int N=10000010,M=(1<<22)+5;
      int n,m,i,u,v,f[N],have,goal;
      int g[M],nxt[N],q[1000000];
      U e[N][3],ans[N/32+10];
      U s;
      ll w;
      inline bool cmp(int x,int y){return e[x][2]<e[y][2];}
      inline U getnxt(){
      s ^= s << 13;
      s ^= s >> 17;
      s ^= s << 5;
      return s;
      }
      int F(int x){return f[x]==x?x:f[x]=F(f[x]);}
      inline void merge(int x){
      	int a=e[x][0],b=e[x][1];
      	//printf("merge %d %d\n",a,b);
      	if(F(a)!=F(b)){
      		have++;
      		ans[x>>5]|=1U<<(x&31);
      		f[f[a]]=f[b];
      	}
      }
      inline void solve(int x){
      	if(g[x]<0)return;
      	if(nxt[g[x]]<0){
      		merge(g[x]);
      		return;
      	}
      	int cnt=0;
      	for(int i=g[x];~i;i=nxt[i])q[cnt++]=i;
      	sort(q,q+cnt,cmp);
      	for(int i=0;i<cnt;i++)merge(q[i]);
      }
      int main(){
      	scanf("%d%d%u",&n,&m,&s);
      	goal=(n-1)/2+1;
      	goal=min(goal,n-1);
      	U mask=~0U;
      	for(i=0;i<M;i++)g[i]=-1;
      	for(i=0;i<m;i++){
      		u=getnxt()%n;
      		v=getnxt()%n;
      		w=getnxt()>>2;
      		w=w*getnxt();
      		w>>=8;
      		e[i][0]=u;
      		e[i][1]=v;
      		e[i][2]=w&mask;
      		w>>=32;
      		nxt[i]=g[w];
      		g[w]=i;
      		//printf("%d %d %llu\n",u,v,w);
      	}
      	for(i=0;i<n;i++)f[i]=i;
      	for(i=0;i<M&&have<goal;i++)solve(i);
      	m=(m-1)/32;
      	for(i=0;i<=m;i++)printf("%u ",ans[i]);
      }
      

        

      K. Dance

      留坑。

       

      L. Impress Her

      對于一個$A\times B$的包圍矩形,因為四連通,至少消耗$A+B$個點,故直接枚舉每個矩形內部所有點的時間復雜度為$O(n^3)$。

      對于每個點記錄其所屬矩形,對于每個矩形$x$,枚舉內部所有點,檢查$x$是否包含該點所屬矩形即可,用時間戳來$O(1)$判重。

      #include<stdio.h>
      #include<iostream>
      #include<string.h>
      #include<string>
      #include<ctype.h>
      #include<math.h>
      #include<set>
      #include<map>
      #include<vector>
      #include<queue>
      #include<bitset>
      #include<algorithm>
      #include<time.h>
      using namespace std;
      void fre() {  }
      #define MS(x, y) memset(x, y, sizeof(x))
      #define ls o<<1
      #define rs o<<1|1
      typedef long long LL;
      typedef unsigned long long UL;
      typedef unsigned int UI;
      template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
      template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
      const int N = 505, M = 1e6 + 10, Z = 1e9 + 7, inf = 0x3f3f3f3f;
      template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
      int casenum, casei;
      int n, m;
      int a[N][N];
      bool vis[M];
      bool vs[N][N];
      int dfn[M];
      int ymin[M];
      int ymax[M];
      int xmin[M];
      int xmax[M];
      
      const int dy[4] = {-1,0,0,1};
      const int dx[4] = {0,-1,1,0};
      void dfs(int y, int x)
      {
      	if(vs[y][x])return;
      	vs[y][x] = 1;
      	gmin(ymin[a[y][x]], y);
      	gmax(ymax[a[y][x]], y);
      	gmin(xmin[a[y][x]], x);
      	gmax(xmax[a[y][x]], x);
      	for(int k = 0; k < 4; ++k)
      	{
      		int yy = y + dy[k];
      		int xx = x + dx[k];
      		if(a[yy][xx] == a[y][x])
      		{
      			dfs(yy, xx);
      		}
      	}
      }
      int main()
      {
      	while(~scanf("%d%d",&n, &m))
      	{
      		for(int i = 1; i <= n; ++i)
      		{
      			for(int j = 1; j <= m; ++j)
      			{
      				scanf("%d", &a[i][j]);
      			}
      		}
      		MS(vis, 0);
      		MS(vs,0);
      		MS(ymin, 63);
      		MS(ymax, 0);
      		MS(xmin, 63);
      		MS(xmax, 0);
      		for(int i = 1; i <= n; ++i)
      		{
      			for(int j = 1; j <= m; ++j)
      			{
      				if(!vis[ a[i][j] ])
      				{
      					vis[ a[i][j] ] = 1;
      					dfs(i, j);
      				}
      			}
      		}
      		MS(dfn, 0);
      		int tim = 0;
      		int ans = 0;
      		for(int i = 1; i <= n; ++i)
      		{
      			for(int j = 1; j <= m; ++j)
      			{
      				int col = a[i][j];
      				if(vis[col])
      				{
      					vis[col] = 0;
      					++tim;
      					for(int y = ymin[col]; y <= ymax[col]; ++y)
      					{
      						for(int x = xmin[col]; x <= xmax[col]; ++x)
      						{
      							int c = a[y][x];
      							if(c != col && dfn[c] != tim
      							 && ymin[c] >= ymin[col]
      							 && ymax[c] <= ymax[col]
      							 && xmin[c] >= xmin[col]
      							 && xmax[c] <= xmax[col]
      							 )
      							{
      								dfn[c] = tim;
      								++ans;
      							}
      						}
      					}
      				}
      			}
      		}
      		printf("%d\n", ans);
      	}
      	return 0;
      }
      
      /*
      【trick&&吐槽】
      
      
      【題意】
      
      
      【分析】
      
      
      【時間復雜度&&優化】
      
      
      */
      

        

      posted @ 2018-03-12 01:37  Claris  閱讀(1018)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 久久热在线视频精品视频| 精品国产中文字幕懂色| xbox免费观看高清视频的软件| 亚洲成人av在线系列| 蜜桃av无码免费看永久| XXXXXHD亚洲日本HD| 国产精品538一区二区在线| 久久亚洲精品国产精品| 丁香五月亚洲综合在线国内自拍| 久久成人 久久鬼色| 人妻少妇| 国产成人精品无码专区| 99久久久无码国产麻豆| 免费无码av片在线观看中文| 亚洲一区二区三区人妻天堂| 国内精品久久久久影院网站| 亚洲精品美女一区二区| 成人嫩草研究院久久久精品| 又粗又硬又黄a级毛片| 高颜值午夜福利在线观看| 激情五月开心婷婷深爱| 亚洲一区二区三区影院| 日区中文字幕一区二区| 中文字幕亚洲日韩无线码| 巫溪县| 精品无码国产一区二区三区AV| 国内熟妇人妻色在线视频| 亚洲中文字幕国产综合| 久久97超碰色中文字幕| 最新国产精品中文字幕| 隆子县| 人与禽交av在线播放| 狠狠精品久久久无码中文字幕| 高清偷拍一区二区三区| 久久老熟妇精品免费观看| 欧洲无码一区二区三区在线观看| 国产高清精品在线91| 亚洲东京色一区二区三区| 欧美成人片在线观看| 亚洲精品乱码久久久久久蜜桃图片| 日韩中文字幕有码av|