zoukankan      html  css  js  c++  java
  • XVIII Open Cup named after E.V. Pankratiev. Eastern Grand Prix

    A. Artifacts

    建立语法分析树,首先根据上下界判断是否有解,然后将所有数按下界填充,线段树判断是否存在和超过$K$的子区间。

    B. Brackets and Dots

    最优解中一定包含一对中间都是点的$()$,set维护所有这种pair即可。

    #include<cstdio>
    #include<set>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef pair<int,int>P;
    const int N=500010;
    int n,i,m,x,y;
    set<int>A;
    set<P>B;
    char a[N];
    inline bool gao(int x,int y){
    	set<P>::iterator it=B.lower_bound(P(x,-1));
    	if(it==B.end())return 0;
    	if(it->second>y)return 0;
    	int l=it->first,r=it->second;
    	B.erase(it);
    	set<int>::iterator i=A.find(l),j=A.find(r);
    	int pre=0,nxt=0;
    	if(i!=A.begin()){
    		i--;
    		if(a[*i]=='(')pre=*i;
    	}
    	j++;
    	if(j!=A.end()){
    		if(a[*j]==')')nxt=*j;
    	}
    	A.erase(l);
    	A.erase(r);
    	if(pre&&nxt)B.insert(P(pre,nxt));
    	return 1;
    }
    int main(){
    	scanf("%s",a+1);
    	n=strlen(a+1);
    	for(i=1;i<=n;i++){
    		A.insert(i);
    		if(a[i]=='('&&a[i+1]==')')B.insert(P(i,i+1));
    	}
    	scanf("%d",&m);
    	while(m--){
    		scanf("%d%d",&x,&y);
    		int ans=0;
    		while(gao(x,y))ans++;
    		printf("%d
    ",ans*2);
    	}
    }
    

      

    C. Crossword

    首先$O(n^2)$预处理出竖着的两条对于每种间隔的贡献,然后$O(n^2)$枚举横着的摆法,再根据预处理的数组求出每个位置竖着的放法,前缀和优化即可。

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

    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    using namespace std;
    string a[9];
    int q[9],i;
    long long ans;
    int f[555],g[555];
    int wc[160][29][29],wd[160][29][29];
    inline int cal(const string&A,int d,char x,char y){
    	int ret=0;
    	for(int i=d;i<A.size();i++)if(A[i-d]==x&&A[i]==y)ret++;
    	return ret;
    }
    void pre(const string&A,int w[][29][29]){
    	for(int i=0;i<160;i++)for(int j=0;j<29;j++)for(int k=0;k<29;k++)w[i][j][k]=0;
    	for(int i=0;i<A.size();i++)for(int j=i+1;j<A.size();j++){
    		w[j-i][A[i]][A[j]]++;
    	}
    }
    void solve(const string&A,const string&B,const string&C,const string&D){
    	int i,j,k,x,y,z,o,dx,dy;
    	int lena=A.size(),lenb=B.size(),lenc=C.size(),lend=D.size();
    	pre(C,wc);
    	pre(D,wd);
    	for(dy=-150;dy<=150;dy++){
    		int L=max(0,dy),R=min(lena-1,dy+lenb-1);
    		if(R-L+1<3)continue;
    		for(dx=2;dx<=150;dx++){
    			f[L-1]=0;
    			for(i=L;i<=R;i++){
    				/*f[i]=cal(C,dx,A[i],B[i-dy]);
    				g[i]=cal(D,dx,A[i],B[i-dy]);
    				if(f[i]!=wc[dx][A[i]][B[i-dy]]){
    					printf("%d %d %d
    ",dx,A[i],B[i-dy]);
    					for(int t=0;t<C.size();t++)printf("%d ",C[t]);
    					puts("");
    					printf("%d %d
    ",f[i],wc[dx][A[i]][B[i-dy]]);
    					while(1);
    				}*/
    				f[i]=wc[dx][A[i]][B[i-dy]],g[i]=wd[dx][A[i]][B[i-dy]];
    			}
    			for(i=L;i<=R;i++)f[i]+=f[i-1];
    			for(i=L+2;i<=R;i++)ans+=f[i-2]*g[i];
    		}
    	}
    }
    int main(){
    	for(i=1;i<=4;i++){
    		cin>>a[i];
    		for(int j=0;j<a[i].size();j++)a[i][j]-='a'-1;
    		q[i]=i;
    	}
    	do{
    		solve(a[q[1]],a[q[2]],a[q[3]],a[q[4]]);
    	}while(next_permutation(q+1,q+5));
    	printf("%lld",ans);
    }
    

      

    D. Digit

    从高位到低位贪心。

    #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, l;
    int cnt[10];
    vector<int>vt[10];
    int w[10];
    bool ok[N];
    int ans[N];
    char s[N];
    int solve()
    {
    	MS(ok, 0);
    	MS(w, 0);
    	
    	int p = n + 1;
    	while(p > 1 && s[p - 1] == '9')--p;
    	ok[p - 1] = 1;
    	
    	bool can = ok[0];
    	for(int i = 1; i <= n; ++i)
    	{
    		can |= ok[i];
    		if(can)
    		{
    			for(int j = 1; j <= s[i] - '0'; ++j)w[j]++;
    		}
    		else
    		{
    			int top = s[i] - '0' - 1;
    			if(top == 0 && s[i] == '1')top = 1;
    			for(int j = 1; j <= top; ++j)w[j]++;
    		}
    	}
    	 
    	
    	int v = -1;
    	int g = -1;
    	for(int i = 9; i >= 0; --i)
    	{
    		if(w[i] > g)
    		{
    			g = w[i];
    			v = i;
    		}
    	}
    	return v;
    }
    void table()
    {
    	for(n = 1; n <= 9999; ++n)
    	{
    		int x = n;
    		while(x)
    		{
    			++cnt[x % 10];
    			x /= 10;
    		}
    		int v = -1;
    		int g = -1;
    		for(int i = 9; i >= 0; --i)
    		{
    			if(cnt[i] > g)
    			{
    				g = cnt[i];
    				v = i;
    			}
    		}
    		ans[n] = v;
    		//vt[v].push_back(n);
    	}
    	for(int i = 1; i <= 9; ++i)
    	{
    		printf("# %d: ", i);
    		for(auto x : vt[i])printf("%d ", x); puts("");
    	}
    }
    int main()
    {
    	//table();
    	while(~scanf("%s",s + 1))
    	//for(int x = 1; x <= 9999; ++x)
    	{
    		//sprintf(s + 1, "%d", x);
    		n = strlen(s + 1);
    		int ans1 = solve();
    		//printf("%d:
    ", x);
    		printf("%d
    ", ans1);
    		
    		/*
    		int ans2 = ans[x];
    		printf("%d
    ", ans2);
    		if(ans1 != ans2)
    			while(1);
    		*/
    		
    		
    		//int x; sscanf(s + 1, "%d", &x);
    		//printf("%d
    ", ans[x]);
    	}
    	return 0;
    }
    
    /*
    【trick&&吐槽】
    
    
    【题意】
    
    
    【分析】
    
    
    【时间复杂度&&优化】
    
    
    */
    

      

    E. Enormous Table

    找规律。

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<algorithm>
    using namespace std;
    const int N= 1e6 + 10;
    typedef long long LL;
    
    LL a, b;
    int main(){
    	while(~ scanf("%lld%lld", &a, &b)){
    		LL x = a + b - 2;
    		LL y = (1 + x) * x / 2;
    		LL ans;
    		if((a + b) & 1) ans = y + a;
    		else ans = y + b;
    		printf("%lld
    ", ans);
    	}	
    }
    
    /*
    4 7 1 4
    1 2
    1 2
    1 4
    2 3
    2 3
    3 4
    3 4
    
    4 3 1 2
    1 2
    2 4
    4 3
    
    5 8 3 1
    3 2
    5 2
    3 4
    4 5
    4 1
    2 1
    3 5
    3 1
    
    */
    

      

    F. Funny Language

    首先可以$O(nlog n)$枚举出所有位于同一段序列内部的区间$gcd$,只需要考虑横跨了多个序列的情况。

    考虑容斥,设$f_d$表示$d|gcd$的方案数,则实际值$g_d=f_d-g_{2d}-g_{3d}-...$,可以在$O(nlog n)$的时间内求出所有$g$。

    考虑如何求$f_d$:对于每个序列计算有多少个前后缀是$d$的倍数,以及整个序列是否是$d$的倍数,枚举横跨序列的个数用组合数计算答案即可。

    时间复杂度$O(nd(n))$。

    #include<cstdio>
    #include<vector>
    using namespace std;
    const int N=80010,P=1000000007;
    int D,i,j,fac[N],inv[N],ans[N],fin;
    int n,len[N],st[N],en[N],pool[N],cur,base;
    int vis[N],vl[N],vr[N],ok[N],all,m,q[N];
    int sl[2],sr[2],slr[2];
    vector<int>vpre[N],vsuf[N],vall[N];
    int gcd(int a,int b){return b?gcd(b,a%b):a;}
    inline int C(int n,int m){return n<m?0:1LL*fac[n]*inv[m]%P*inv[n-m]%P;}
    inline void up(int&a,int b){a=a+b<P?a+b:a+b-P;}
    inline void solve(int L,int R){
    	static int a[N],l[N],v[N];
    	int n=R-L+1,i,j;
    	for(i=1;i<=n;i++)a[i]=pool[L+i-1];
    	for(i=0;i<=n;i++)l[i]=v[i]=0;
    	for(i=1;i<=n;i++)for(v[i]=a[i],j=l[i]=i;j;j=l[j]-1){
    		v[j]=gcd(v[j],a[i]);
    		while(l[j]>1&&gcd(a[i],v[l[j]-1])==gcd(a[i],v[j]))l[j]=l[l[j]-1];
    		up(ans[v[j]],1LL*(j-l[j]+1)*base%P);
    	}
    }
    inline void visit(int x){
    	if(vis[x]==D)return;
    	vis[x]=D;
    	vl[x]=vr[x]=ok[x]=0;
    	q[++m]=x;
    }
    inline int work(){
    	int i,j,k,x,y,ret,ans=0;
    	all=m=0;
    	for(i=D;i<N;i+=D){
    		for(j=0;j<vall[i].size();j++){
    			x=vall[i][j];
    			visit(x);
    			ok[x]=1;
    			all++;
    		}
    		for(j=0;j<vpre[i].size();j++){
    			x=vpre[i][j];
    			visit(x);
    			vl[x]++;
    		}
    		for(j=0;j<vsuf[i].size();j++){
    			x=vsuf[i][j];
    			visit(x);
    			vr[x]++;
    		}
    	}
    	for(i=0;i<2;i++)sl[i]=sr[i]=slr[i]=0;
    	for(i=1;i<=m;i++){
    		x=q[i];
    		up(sl[ok[x]],vl[x]);
    		up(sr[ok[x]],vr[x]);
    		up(slr[ok[x]],1LL*vl[x]*vr[x]%P);
    		//printf("x=%d vl=%d vr=%d ok=%d
    ",x,vl[x],vr[x],ok[x]);
    	}
    	//printf("all=%d
    ",all);
    	for(x=0;x<2;x++)for(y=0;y<2;y++){
    		ret=all-x-y;
    		if(ret<0)continue;
    		for(k=0;k<=ret;k++){
    			if(n-k-2<0)continue;
    			int now=1LL*C(ret,k)*fac[k]%P*(n-k-1)%P*fac[n-k-2]%P;
    			int tmp=1LL*sl[x]*sr[y]%P;
    			if(x==y)tmp=(tmp-slr[x]+P)%P;
    			//printf("x=%d y=%d ret=%d k=%d now=%d tmp=%d
    ",x,y,ret,k,now,tmp);
    			ans=(1LL*now*tmp+ans)%P;
    		}
    	}
    	//if(ans)printf("ans[%d]=%d
    ",D,ans);
    	return ans;
    }
    int main(){
    	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;
    	
    	scanf("%d",&n);
    	base=1LL*fac[n-1]*n%P;
    	for(i=1;i<=n;i++){
    		scanf("%d",&len[i]);
    		st[i]=cur+1;
    		en[i]=cur+len[i];
    		for(j=st[i];j<=en[i];j++)scanf("%d",&pool[j]);
    		cur+=len[i];
    		int pre=pool[st[i]],suf=pool[en[i]];
    		for(j=st[i];j<=en[i];j++){
    			pre=gcd(pre,pool[j]);
    			vpre[pre].push_back(i);
    		}
    		vall[pre].push_back(i);
    		for(j=en[i];j>=st[i];j--){
    			suf=gcd(suf,pool[j]);
    			vsuf[suf].push_back(i);
    		}
    	}
    	for(D=1;D<N;D++)ans[D]=work();
    	for(i=N-1;i;i--)for(j=i+i;j<N;j+=i)ans[i]=(ans[i]-ans[j]+P)%P;
    	for(i=1;i<=n;i++)solve(st[i],en[i]);
    	for(i=1;i<N;i++)fin=(1LL*i*ans[i]+fin)%P;
    	printf("%d",fin);
    }
    

      

    G. Game of Tic-Tac-Toe

    总状态只有$2 imes 3^9$,博弈DP后即可得到下棋策略。

    #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 = 1010, 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;
    int f[3*3*3*3*3*3*3*3*3][2];
    int a[3][3];
    int check()
    {
    	int j = 0;
    	for(int i = 0; i < 3; ++i)
    	{
    		if(a[i][j] == 0 && a[i][j + 1] == 0 && a[i][j + 2] == 0)return 0;
    		if(a[j][i] == 0 && a[j + 1][i] == 0 && a[j + 2][i] == 0)return 0;
    		if(a[i][j] == 1 && a[i][j + 1] == 1 && a[i][j + 2] == 1)return 1;
    		if(a[j][i] == 1 && a[j + 1][i] == 1 && a[j + 2][i] == 1)return 1;
    	}
    	
    	if(a[0][0] == 0 && a[1][1] == 0 && a[2][2] == 0)return 0;
    	if(a[0][2] == 0 && a[1][1] == 0 && a[2][0] == 0)return 0;
    	if(a[0][0] == 1 && a[1][1] == 1 && a[2][2] == 1)return 1;
    	if(a[0][2] == 1 && a[1][1] == 1 && a[2][0] == 1)return 1;
    	
    	return 2;
    }
    int v[10];
    void getA(int x)
    {
    	for(int j = 0; j < 9; ++j)
    	{
    		a[j / 3][j % 3]  = x % 3;
    		if(a[j / 3][j % 3]) -- a[j / 3][j % 3];
    		else a[j / 3][j % 3] = 2;
    		x /= 3;
    	}
    }
    int main()
    {
    	int top = 3*3*3*3*3*3*3*3*3;
    	v[0] = 1; for(int i = 1; i <= 9; ++i)v[i] = v[i - 1] * 3;
    	
    	for(int i = top - 1; i >= 0; --i)
    	{
    		getA(i);
    		int win = check();
    		if(win < 2)
    		{
    			//printf("win status %d: %d
    ", i, win);
    			f[i][0] = f[i][1] = win;
    			continue;
    		}
    		
    		bool end = 1;
    		for(int j = 0; j < 9; ++j)
    		{
    			if(a[j / 3][j % 3] == 2)
    			{
    				end = 0;
    			}
    		}
    		if(end)
    		{
    			f[i][0] = f[i][1] = 2;
    			continue;
    		}
    		
    		for(int k = 0; k < 2; ++k)//who play
    		{
    			bool can_draw = 0;
    			f[i][k] = -1;
    			for(int j = 0; j < 9; ++j)
    			{
    				if(a[j / 3][j % 3] == 2)
    				{
    					int nxt = i + v[j] * (k + 1);
    					if(f[nxt][1 ^ k] == k)
    					{
    						f[i][k] = k;
    					}
    					else if(f[nxt][1 ^ k] == 2)
    					{
    						can_draw = 1;
    					}
    				}
    			}
    			if(f[i][k] == -1)
    			{
    				f[i][k] = can_draw ? 2 : (1 ^ k);
    			}
    		}
    	}
    	//printf("%d
    ", f[0][0]);
    	
    	char C;
    	scanf(" %c", &C);
    	{
    		int me = 1, ene = 0;
    		int step = 0;
    		int now = 0;
    		if(C == 'O')
    		{
    			int y, x;
    			scanf("%d%d", &y, &x);
    			--y; --x;
    			now += v[y * 3 + x] * 1;
    			++step;
    		}
    		getA(now);
    		//printf("sta: %d, %d
    ", now, f[now][me]);
    		
    		while(step < 9)
    		{
    			int y = -1;
    			int x = -1;
    			for(int i = 0; i < 3; ++i)
    			{
    				for(int j = 0; j < 3; ++j)if(a[i][j] == 2)
    				{
    					int nxt = now + v[i * 3 + j] * 2;
    					//printf("ene: %d %d
    ", nxt, f[nxt][ene]);
    					if(f[nxt][ene] != ene)
    					{
    						y = i;
    						x = j;
    					}
    				}
    			}
    			printf("%d %d
    ", y + 1, x + 1);
    			fflush(stdout);
    			now += v[y * 3 + x] * 2;
    			++step;
    			getA(now);
    			
    			char s[100];
    			scanf("%s", s);
    			if(isalpha(s[0]))return 0;
    			sscanf(s, "%d", &y);
    			scanf("%s", s);
    			sscanf(s, "%d", &x);
    			--y; --x;
    			now += v[y * 3 + x] * 1;
    			++step;
    			getA(now);
    		}
    	}
    	return 0;
    }
    
    /*
    【trick&&吐槽】
    
    
    【题意】
    
    
    【分析】
    
    
    【时间复杂度&&优化】
    
    
    */
    

      

    H. Hill and Subhill

    高维差分。

    #include<cstdio>
    #include<cstring>
    #define FOR(i,a,b) for(int i=a;i<=b;i++)
    #define FOV(i,a,b) for(int i=a;i>=b;i--)
    #define CLR(a) memset(a,0,sizeof a)
    #define U 105][105][105
    #define FFF FOR(i,1,N)FOR(j,1,i)FOR(k,1,j)
    #define VVV FOV(i,N,1)FOV(j,i,1)FOV(k,j,1)
    typedef long long LL;
    int N,M,Q,x,y,z,a,d3as[U],d3ae[U],d3ds[U],d3de[U];
    LL d2a[U],d2d[U],d1[U],suffix1d[U],suffix2d[U],s1[U],s2[U],s31[U],s32[U];
    inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
    void solve(){
      int x,y,z,a;
      CLR(d3as);
      CLR(d3ae);
      CLR(d3ds);
      CLR(d3de);
      CLR(d2a);
      CLR(d2d);
      CLR(d1);
      CLR(suffix1d);
      CLR(suffix2d);
      CLR(s1);
      CLR(s2);
      CLR(s31);
      CLR(s32);
      for(int i=0;i<M;i++){
        read(x),read(y),read(z),read(a);
        d3as[x][y][z]++;
        d3as[x+a][y+a][z+a]--;
        d3ae[x+a][y+a][z]--;
        d3ae[x+a][y+a][z+a]++;
        d3ds[x+a][y][z]--;
        d3ds[x+a][y+a][z+a]++;
        d3de[x+a][y+a][z]++;
        d3de[x+a][y+a][z+a]--;
      }
      FFF{
        d2a[i][j][k]+=d3as[i][j][k];
        d2a[i][j][k]+=d3ae[i][j][k];
        d2d[i][j][k]+=d3ds[i][j][k];
        d2d[i][j][k]+=d3de[i][j][k];
        d3as[i+1][j+1][k+1]+=d3as[i][j][k];
        d3ae[i][j][k+1]+=d3ae[i][j][k];
        d3ds[i][j+1][k+1]+=d3ds[i][j][k];
        d3de[i][j][k+1]+=d3de[i][j][k];
      }
      FFF{
        d1[i][j][k]+=d2a[i][j][k];
        d1[i][j][k]+=d2d[i][j][k];
        d2a[i+1][j+1][k]+=d2a[i][j][k];
        d2d[i][j+1][k]+=d2d[i][j][k];
      }
      FFF{
        suffix1d[i][j][k]+=d1[i][j][k];
        d1[i+1][j][k]+=d1[i][j][k];
      }
      VVV suffix1d[i][j][k]+=suffix1d[i+1][j][k];
      VVV suffix2d[i][j][k]+=suffix1d[i][j][k]+suffix2d[i+1][j+1][k];
      VVV s1[i][j][k]+=suffix2d[i][j][k]+s1[i+1][j+1][k+1];
      VVV s2[i][j][k]+=suffix2d[i][j][k]+s2[i][j][k+1];
      VVV s31[i][j][k]+=suffix1d[i][j][k]+s31[i][j+1][k];
      VVV s32[i][j][k]+=s31[i][j][k]+s32[i][j+1][k+1];
      VVV s31[i][j][k]+=s31[i][j][k+1];
      while(Q--){
        read(x),read(y),read(z),read(a);
        LL ans=s1[x][y][z]-s1[x+a][y+a][z+a];
        ans-=s2[x+a][y+a][z]-s2[x+a][y+a][z+a];
        ans+=s31[x+a][y+a][z]-s31[x+a][y+a][z+a];
        ans-=s32[x+a][y][z]-s32[x+a][y+a][z+a];
        printf("%lld
    ",ans);
      }
    }
    int main(){
      while(~scanf("%d%d%d",&N,&M,&Q))solve();
      return 0;
    }
    

      

    I. It is panic?

    按题意模拟。

    #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 = 1010, 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];
    int main()
    {
    	while(~scanf("%s",s))
    	{
    		int n = strlen(s);
    		int l = -1;
    		while(l < n - 1 && s[l + 1] == 'A')++l;
    		int r = n;
    		while(r > 0 && s[r - 1] == '!')--r;
    		if(l >= 0 && r < n && r == l + 1)puts("Panic!");
    		else puts("No panic");
    	}
    	return 0;
    }
    
    /*
    【trick&&吐槽】
    
    
    【题意】
    
    
    【分析】
    
    
    【时间复杂度&&优化】
    
    
    */
    

      

    J. JokeCoin

    按左端点排序,树状数组维护右端点即可优化DP至$O(nlog n)$。

    #include<cstdio>
    #include<vector>
    #include<algorithm>
    using namespace std;
    typedef vector<int>V;
    typedef long long ll;
    const int N=200010,M=25,P=1000000007;
    
    int n, m;
    struct A
    {
    	int st, ed, v;
    }a[N];
    inline bool cmp(const A&a,const A&b){
    	return a.st<b.st;
    }
    ll ans,f[N];
    void ins(int x,ll p){for(;x<N;x+=x&-x)f[x]=max(f[x],p);}
    ll ask(int x){ll t=0;for(;x;x-=x&-x)t=max(t,f[x]);return t;}
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i = 1; i <= n; i ++){
    		int x, y, z, xx, yy, zz, v;
    		scanf("%d:%d:%d%d:%d:%d%d", &x, &y, &z, &xx, &yy, &zz, &v);
    		int t1 = x * 3600 + y * 60 + z;
    		int t2 = xx * 3600 + yy * 60 + zz;
    		v -= (t2 - t1) * m;
    		a[i].st = t1;
    		a[i].ed = t2;
    		a[i].v = v;
    	}
    	for(int i=1;i<=n;i++)a[i].st+=5,a[i].ed+=5;
    	sort(a+1,a+n+1,cmp);
    	for(int i=1;i<=n;i++){
    		ll dp=ask(a[i].st)+a[i].v;
    		ans=max(ans,dp);
    		ins(a[i].ed,dp);
    	}
    	printf("%lld",ans);
    	/*for(int i = 1; i <= n; i ++){
    		printf("%d %d %d
    ", a[i].st, a[i].ed, a[i].v);
    	}*/
    }
    /*
    4 0
    03:00:00 10:10:00 20
    01:00:00 02:30:00 50
    16:10:00 19:00:00 100
    02:30:00 22:00:00 200
    
    3 1
    16:59:00 17:00:00 100
    01:01:01 01:01:11 20
    12:00:00 13:00:00 3601
    
    4 10
    00:00:05 00:01:55 1100
    00:00:10 00:00:21 100
    00:01:50 00:02:00 80
    23:59:00 23:59:05 40
    
    */
    

      

    K. King and ICPC

    分治,预处理出$mid$到$[l,r]$每个点的背包,然后利用这个信息处理所有经过$mid$的询问。

    时间复杂度$O((nd+m)log n+md)$。

    #include<cstdio>
    #include<vector>
    using namespace std;
    typedef vector<int>V;
    typedef long long ll;
    const int N=50010,M=55;
    const ll inf=1LL<<60;
    int n,m,q,i,j,a[N][3];
    ll f[N][M],g[N][M];
    int e[300010][2];
    ll ans[300010];
    inline void up(ll&a,ll b){a<b?(a=b):0;}
    void solve(int l,int r,V v){
    	if(l>r||!v.size())return;
    	int mid=(l+r)>>1;
    	int i,j,k;
    	//[l..mid] [mid+1..r]
    	for(i=l;i<=mid+1;i++)for(j=0;j<m;j++)f[i][j]=-inf;
    	f[mid+1][0]=0;
    	for(i=mid;i>=l;i--)for(j=0;j<m;j++)for(k=0;k<3;k++)up(f[i][(j+a[i][k])%m],f[i+1][j]+a[i][k]);
    	for(i=mid;i<=r;i++)for(j=0;j<m;j++)g[i][j]=-inf;
    	g[mid][0]=0;
    	for(i=mid+1;i<=r;i++)for(j=0;j<m;j++)for(k=0;k<3;k++)up(g[i][(j+a[i][k])%m],g[i-1][j]+a[i][k]);
    	V vl,vr;
    	for(i=0;i<v.size();i++){
    		int x=v[i];
    		if(e[x][1]<mid)vl.push_back(x);
    		else if(e[x][0]>mid)vr.push_back(x);
    		else{
    			for(j=0;j<m;j++)up(ans[x],f[e[x][0]][j]+g[e[x][1]][(m-j)%m]);
    		}
    	}
    	solve(l,mid-1,vl);
    	solve(mid+1,r,vr);
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for(i=1;i<=n;i++)for(j=0;j<3;j++)scanf("%d",&a[i][j]);
    	scanf("%d",&q);
    	V v;
    	for(i=1;i<=q;i++){
    		scanf("%d%d",&e[i][0],&e[i][1]);
    		ans[i]=-inf;
    		v.push_back(i);
    	}
    	solve(1,n,v);
    	for(i=1;i<=q;i++){
    		if(ans[i]<0)ans[i]=-1;
    		printf("%lld
    ",ans[i]);
    	}
    }
    

      

    L. Longest Simple Paths

    Dijkstra求出最短路树后点分治统计即可。

    #include<cstdio>
    #include<algorithm>
    const int N=30010,M=120010,inf=~0U>>1;
    int n,m,k,i,x,y,z,g[N],v[M],w[M],nxt[M],ok[M],ed,d[N],vis[N],son[N],f[N],size,now,T,pos[N];
    struct E{int x,y,w;E(){}E(int _x,int _y,int _z){x=_x,y=_y,w=_z;}}a[M];
    inline bool cmp(E a,E b){return a.x==b.x?a.y>b.y:a.x<b.x;}
    inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
    inline void add(int x,int y,int z){v[++ed]=y;w[ed]=z;nxt[ed]=g[x];ok[ed]=1;g[x]=ed;}
    struct Num{
      int x,y;
      Num(){x=y=0;}
      Num(int _x,int _y){x=_x,y=_y;}
      inline Num operator+(Num b){
        if(x==b.x)return Num(x,y+b.y);
        return x<b.x?b:Num(x,y);
      }
      inline void operator+=(Num b){*this=*this+b;}
    }tmp[N],ans;
    inline void up(int x,Num y){
      if(pos[x]<T)pos[x]=T,tmp[x]=Num();
      tmp[x]+=y;
    }
    inline Num get(int x){
      if(pos[x]<T)return Num();
      return tmp[x];
    }
    struct PI{
      int x,y;
      PI(){}
      PI(int _x,int _y){x=_x,y=_y;}
      inline PI operator+(PI b){return x<=b.x?PI(x,y):b;}
    }val[65537];
    void build(int x,int a,int b){
      val[x]=PI(inf,a);
      if(a==b)return;
      int mid=(a+b)>>1;
      build(x<<1,a,mid),build(x<<1|1,mid+1,b);
    }
    inline void change(int x,int a,int b,int c,int d){
      if(a==b){val[x].x=d;return;}
      int mid=(a+b)>>1;
      c<=mid?change(x<<1,a,mid,c,d):change(x<<1|1,mid+1,b,c,d);
      val[x]=val[x<<1]+val[x<<1|1];
    }
    void dfs(int x){
      vis[x]=1;
      for(int i=g[x];i;i=nxt[i])if(!vis[v[i]]&&d[x]+w[i]==d[v[i]])a[++m]=E(x,v[i],w[i]),dfs(v[i]);
    }
    void findroot(int x,int pre){
      son[x]=1;f[x]=0;
      for(int i=g[x];i;i=nxt[i])if(ok[i]&&v[i]!=pre){
        findroot(v[i],x);
        son[x]+=son[v[i]];
        if(son[v[i]]>f[x])f[x]=son[v[i]];
      }
      if(size-son[x]>f[x])f[x]=size-son[x];
      if(f[x]<f[now])now=x;
    }
    void dfscal(int x,int pre,int dep,int sum){
      if(dep>=k)return;
      Num t=get(k-dep);
      if(t.y)ans+=Num(t.x+sum,t.y);
      for(int i=g[x];i;i=nxt[i])if(ok[i]&&v[i]!=pre)dfscal(v[i],x,dep+1,sum+w[i]);
    }
    void dfsadd(int x,int pre,int dep,int sum){
      if(dep>=k)return;
      up(dep,Num(sum,1));
      for(int i=g[x];i;i=nxt[i])if(ok[i]&&v[i]!=pre)dfsadd(v[i],x,dep+1,sum+w[i]);
    }
    void solve(int x){
      int i;
      T++,up(1,Num(0,1));
      for(i=g[x];i;i=nxt[i])if(ok[i])dfscal(v[i],x,2,w[i]),dfsadd(v[i],x,2,w[i]);
      for(i=g[x];i;i=nxt[i])if(ok[i])ok[i^1]=0,f[0]=size=son[v[i]],findroot(v[i],now=0),solve(now);
    }
    int main(){
      read(n),read(m),read(k);k++;
      for(i=1;i<=m;i++){
        read(x),read(y),read(z);
        a[i]=E(x,y,z);
        a[i+m]=E(y,x,z);
      }
      std::sort(a+1,a+m+m+1,cmp);
      for(i=1;i<=m+m;i++)add(a[i].x,a[i].y,a[i].w);
      for(i=2;i<=n;i++)d[i]=inf;
      build(1,1,n),change(1,1,n,1,0);
      while(val[1].x<inf)for(change(1,1,n,x=val[1].y,inf),i=g[x];i;i=nxt[i])if(d[x]+w[i]<d[v[i]])change(1,1,n,v[i],d[v[i]]=d[x]+w[i]);
      m=0,dfs(1);
      for(ed=i=1;i<=n;i++)g[i]=0;
      for(i=1;i<=m;i++)add(a[i].x,a[i].y,a[i].w),add(a[i].y,a[i].x,a[i].w);
      f[0]=size=n,findroot(1,now=0),solve(now);
      return printf("%d %d",ans.x,ans.y),0;
    }
    

      

  • 相关阅读:
    [转]
    Linux
    [转]
    [转]
    Linux 高级网络编程
    [转]
    [译]- 6-1 排列窗体上的控件(Laying Out Widgets on a Form)
    [转]
    [转]
    the thread has exited with code -1073741819
  • 原文地址:https://www.cnblogs.com/clrs97/p/8724497.html
Copyright © 2011-2022 走看看