• 中秋节模拟赛之冷月葬花魂(被虐瞎)


    https://vijos.org/tests/5404825e48c5fcd4578b457a

    果然蒟蒻还是蒟蒻。。

    搜索不会,dp不会,模拟不会T_TT__T_T_T_TT_T_T_T_T_T_T

    什么节奏啊这是。

    t1:小岛的标号

    模拟+bfs。。

    用map被tle了1个点啊!坑啊,,rp低啊。。

    90分滚粗。。。。

    正解:建个trie。。然后在上面维护点的信息,,然后每个组的人员的编号连边,从“Xiaodao”的点作根bfs。。然后每个点的深度就是解。。。。。。。

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    using namespace std;
    #define rep(i, n) for(int i=0; i<(n); ++i)
    #define for1(i,a,n) for(int i=(a);i<=(n);++i)
    #define for2(i,a,n) for(int i=(a);i<(n);++i)
    #define for3(i,a,n) for(int i=(a);i>=(n);--i)
    #define for4(i,a,n) for(int i=(a);i>(n);--i)
    #define CC(i,a) memset(i,a,sizeof(i))
    #define read(a) a=getint()
    #define print(a) printf("%d", a)
    #define dbg(x) cout << #x << " = " << x << endl
    #define printarr(a, n, m) rep(aaa, n) { rep(bbb, m) cout << a[aaa][bbb]; cout << endl; }
    inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
    inline const int max(const int &a, const int &b) { return a>b?a:b; }
    inline const int min(const int &a, const int &b) { return a<b?a:b; }
    
    const int N=50005;
    
    struct ED { int to, next; }e[N*20];
    int cnt, ihead[N], q[N], front, tail, vis[N], d[N];
    inline void add(const int &u, int &v) {
    	e[++cnt].next=ihead[u]; ihead[u]=cnt; e[cnt].to=v;
    	e[++cnt].next=ihead[v]; ihead[v]=cnt; e[cnt].to=u;
    }
    int n, tot;
    void bfs() {
    	q[tail++]=1; vis[1]=1;
    	int u, v;
    	while(front!=tail) {
    		u=q[front++]; if(front==N) front=0;
    		for(int i=ihead[u]; i; i=e[i].next) if(!vis[v=e[i].to]) {
    			vis[v]=1;
    			d[v]=d[u]+1;
    			q[tail++]=v; if(tail==N) tail=0;
    		}
    	}
    }
    const int Tcnt=1000005;
    int T[Tcnt][55], id[Tcnt], sz;
    void ins(char s[], int dt) {
    	int len=strlen(s), now=0;
    	rep(i, len) {
    		int t;
    		if(s[i]>='A' && s[i]<='Z') t=s[i]-'A'+27;
    		else t=s[i]-'a'+1;
    		if(T[now][t]) now=T[now][t];
    		else now=T[now][t]=++sz;
    	}
    	id[now]=dt;
    }
    int ifind(char s[]) {
    	int len=strlen(s), now=0;
    	rep(i, len) {
    		int t;
    		if(s[i]>='A' && s[i]<='Z') t=s[i]-'A'+27;
    		else t=s[i]-'a'+1;
    		if(T[now][t]) now=T[now][t];
    		else return 0;
    	}
    	return id[now];
    }
    char pr[40];
    void dfs(int now, int t) {
    	if(id[now]) {
    		pr[t]=''; 
    		int an=d[id[now]];
    		printf("%s ", pr);
    		if(an || !strcmp(pr, "Xiaodao")) printf("%d
    ", an);
    		else puts("undefined");
    	}
    	rep(i, 55) if(T[now][i]) {
    		if(i<=26) pr[t]='a'+i-1;
    		else pr[t]='A'+i-27;
    		dfs(T[now][i], t+1);
    	}
    }
    int main() {
    	read(n);
    	char str[30]="Xiaodao";
    	ins(str, ++tot);
    	for1(i, 1, n) {
    		static int idd[5];
    		for1(j, 1, 3) {
    			scanf("%s", str);
    			int t=ifind(str);
    			if(!t) { ins(str, ++tot); idd[j]=tot;  }
    			else idd[j]=t;
    		}
    		for1(j, 1, 3) for1(k, j+1, 3) add(idd[j], idd[k]);
    	}
    	bfs();
    	dfs(0, 0);
    	return 0;
    }
    

    t2:小岛的塔防游戏

    裸暴力50分滚粗T_T

    正解:

    我们发现每个塔的攻击范围是一个正方形,,只不过是斜的45度。。

    那么我们将整个图斜过来(图变成(n+m-1)边长的矩形,每个点(i,j)在这个新图上对应的点是(i-j+m,i+j-1),,很神奇是不是。。。自己画图。。)//upd:根本不用画图,其实这个就是按对角线剖分。。。

    然后问题变为枚举每个点,然后询问在它的攻击范围内有多少个目标,最后排序后取k个

    维护矩形我们用二维前缀和。。。(sum[i][j]表示(i,j)到(1,1)的和)

    sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j]

    询问:

    ask(x1, y1, x2, y2)=sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1]

    自己理解。。

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    using namespace std;
    #define rep(i, n) for(int i=0; i<(n); ++i)
    #define for1(i,a,n) for(int i=(a);i<=(n);++i)
    #define for2(i,a,n) for(int i=(a);i<(n);++i)
    #define for3(i,a,n) for(int i=(a);i>=(n);--i)
    #define for4(i,a,n) for(int i=(a);i>(n);--i)
    #define CC(i,a) memset(i,a,sizeof(i))
    #define read(a) a=getint()
    #define print(a) printf("%d", a)
    #define dbg(x) cout << #x << " = " << x << endl
    #define printarr(a, n, m) rep(aaa, n) { rep(bbb, m) cout << a[aaa][bbb]; cout << endl; }
    inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
    inline const int max(const int &a, const int &b) { return a>b?a:b; }
    inline const int min(const int &a, const int &b) { return a<b?a:b; }
    
    const int N=1005;
    int mp[N][N], a[N][N], sum[N<<1][N<<1], n, m, r, T, cnt, nn, mm;
    char str[1005];
    long long d[N*N], ans;
    
    inline const bool cmp(const int &a, const int &b) { return a>b; }
    inline const int X(const int &x, const int &y) { return x-y+m; }
    inline const int Y(const int &x, const int &y) { return x+y-1; }
    
    inline const int cal(const int &x, const int &y) {
    	int x1=max(x-r, 1), y1=max(y-r, 1), x2=min(nn, x+r), y2=min(mm, y+r);
    	return sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1];
    }
    int main() {
    	read(n); read(m); read(T); read(r);
    	for1(i, 1, n) {
    		scanf("%s", str+1);
    		for1(j, 1, m) {
    			if(str[j]=='O') mp[i][j]=1;
    			else if(str[j]=='X') mp[i][j]=2;
    			if(mp[i][j]==1) {
    				int x=X(i, j), y=Y(i, j);
    				sum[x][y]=1;
    			}
    		}
    	}
    	nn=mm=n+m-1;
    	for1(i, 1, nn) for1(j, 1, mm) sum[i][j]+=sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1];
    	for1(i, 1, n) for1(j, 1, m) if(mp[i][j]==0) {
    		int x=X(i, j), y=Y(i, j);
    		d[++cnt]=cal(x, y);
    	}
    	sort(d+1, d+1+cnt, cmp);
    	long long ans=0;
    	for1(i, 1, T) ans+=d[i];
    	printf("%lld
    ", ans);
    	return 0;
    }
    

    t3:小岛的生日聚会

    不忍吐槽,,我随便乱搞骗分骗了59分。。

    什么节奏。。。

    正解:还不会。听说是dp。。

    t4:小岛的贪吃蛇

    我存图bfs然后队列开不大,,然后wa。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

    证明我是蒟蒻。。

    我也想到头到尾的方法。。但是。。。我存的状态是整个图。。。。

    。。。

    正解:听说维护方向。。。但是维护方向怎么判可行啊。T_T难道是拓展的时候建个8×8的小图然后判么T_T

    50分。。。。没判重。。

    我们只需要维护蛇头,然后维护一个方向向量即可。

    因为长度很短,我们可以考虑用二进制来存方向!(orzzzzzzzzzzzzzzz

    我们两个位来存4种方向,然后每一次移动就直接f<<=2就能空出一个位置了。。

    然后没判重只有50分。。

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    using namespace std;
    #define rep(i, n) for(int i=0; i<(n); ++i)
    #define for1(i,a,n) for(int i=(a);i<=(n);++i)
    #define for2(i,a,n) for(int i=(a);i<(n);++i)
    #define for3(i,a,n) for(int i=(a);i>=(n);--i)
    #define for4(i,a,n) for(int i=(a);i>(n);--i)
    #define CC(i,a) memset(i,a,sizeof(i))
    #define read(a) a=getint()
    #define print(a) printf("%d", a)
    #define dbg(x) cout << (#x) << " = " << (x) << endl
    #define printarr(a, n, m) for1(aaa, 1, n) { for1(bbb, 1, m) cout << a[aaa][bbb] << '	'; cout << endl; }
    inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
    inline const int max(const int &a, const int &b) { return a>b?a:b; }
    inline const int min(const int &a, const int &b) { return a<b?a:b; }
    #define error(x) (!(x)?puts("error"):0)
    
    const int N=22, Q=10000000, dx[]={-1, 1, 0, 0}, dy[]={0, 0, -1, 1}, PW=17;
    int front, tail, n, m, l, mp[N][N], ALL;
    struct dat { int x, y, d, f; }q[Q];
    bool check(int f, int x) {
    	f=((f<<2)|x)&ALL;
    	int s1=0, s2=0;
    	rep(i, l) {
    		int now=(f>>(i<<1))&3;
    		s1+=dx[now];
    		s2+=dy[now];
    		if(s1==0 && s2==0) return false;
    	}
    	return true;
    }
    void bfs() {
    	front=tail=0; ++tail;
    	while(front!=tail) {
    		dat &t=q[front++]; if(front==Q) front=0;
    		int x=t.x, y=t.y, dis=t.d;
    		if(x==1 && y==1) { printf("%d
    ", dis); return; }
    		rep(i, 4) {
    			int fx=dx[i]+x, fy=dy[i]+y;
    			if(fx<1 || fy<1 || fx>n || fy>m || mp[fx][fy]) continue;
    			if(!check(t.f, i)) continue;
    			dat &t2=q[tail++]; if(tail==Q) tail=0;
    			t2.x=fx;
    			t2.y=fy;
    			t2.d=dis+1;
    			t2.f=((t.f<<2)|i)&ALL;
    		}
    	}
    	puts("-1");
    }
    int main() {
    	int cs=0;
    	while(~scanf("%d%d%d", &n, &m, &l) && !(n==0 && m==0 && l==0)) {
    		printf("Case %d: ", ++cs);
    
    		CC(mp, 0);
    		q[0].f=0;
    		q[0].d=0;
    		ALL=(1<<(l<<1))-1;
    
    		int nx=getint(), ny=getint();
    		q[0].x=nx, q[0].y=ny;
    		int &f=q[0].f;
    		rep(i, l-1) {
    			int x=getint(), y=getint();
    			if(x==nx-1) f|=(1<<(i<<1));
    			else if(x==nx+1) f|=(0<<(i<<1));
    			else if(y==ny-1) f|=(3<<(i<<1));
    			else if(y==ny+1) f|=(2<<(i<<1));
    			nx=x; ny=y;
    		}
    		int k=getint();
    		while(k--) { int x=getint(), y=getint(); mp[x][y]=1; } 
    		bfs();
    	}
    	return 0;
    }
    

      

    bfs的判重写在了出队那里,tle了n久,累觉无爱

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    using namespace std;
    #define rep(i, n) for(int i=0; i<(n); ++i)
    #define for1(i,a,n) for(int i=(a);i<=(n);++i)
    #define for2(i,a,n) for(int i=(a);i<(n);++i)
    #define for3(i,a,n) for(int i=(a);i>=(n);--i)
    #define for4(i,a,n) for(int i=(a);i>(n);--i)
    #define CC(i,a) memset(i,a,sizeof(i))
    #define read(a) a=getint()
    #define print(a) printf("%d", a)
    #define dbg(x) cout << (#x) << " = " << (x) << endl
    #define printarr(a, n, m) for1(aaa, 1, n) { for1(bbb, 1, m) cout << a[aaa][bbb] << '	'; cout << endl; }
    inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
    inline const int max(const int &a, const int &b) { return a>b?a:b; }
    inline const int min(const int &a, const int &b) { return a<b?a:b; }
    #define error(x) (!(x)?puts("error"):0)
    
    const int N=22, Q=5000000, dx[]={-1, 1, 0, 0}, dy[]={0, 0, -1, 1};
    int front, tail, n, m, l, mp[N][N], ALL;
    bool vis[N][N][18000];
    struct dat { int x, y, d, f; }q[Q];
    bool check(int f, int x) {
    	f=(f<<2)|x;
    	int s1=0, s2=0;
    	rep(i, l) {
    		int now=(f>>(i<<1))&3;
    		s1+=dx[now];
    		s2+=dy[now];
    		if(s1==0 && s2==0) return false;
    	}
    	return true;
    }
    void bfs() {
    	front=tail=0; ++tail;
    	vis[q[0].x][q[0].y][q[0].f]=1;
    	while(front!=tail) {
    		dat &t=q[front++]; if(front==Q) front=0;
    		int x=t.x, y=t.y, dis=t.d;
    		if(x==1 && y==1) { printf("%d
    ", dis); return; }
    		rep(i, 4) {
    			int fx=dx[i]+x, fy=dy[i]+y;
    			if(fx<1 || fy<1 || fx>n || fy>m || mp[fx][fy] || vis[fx][fy][((t.f<<2)|i)&ALL]) continue;
    			if(!check(t.f, i)) continue;
    			dat &t2=q[tail++]; if(tail==Q) tail=0;
    			t2.x=fx;
    			t2.y=fy;
    			t2.d=dis+1;
    			t2.f=((t.f<<2)|i)&ALL;
    			vis[fx][fy][t2.f]=1;
    		}
    	}
    	puts("-1");
    }
    int main() {
    	int cs=0;
    	while(~scanf("%d%d%d", &n, &m, &l) && !(n==0 && m==0 && l==0)) {
    		printf("Case %d: ", ++cs);
    
    		CC(mp, 0);
    		CC(vis, 0);
    		q[0].f=0;
    		q[0].d=0;
    		ALL=(1<<((l-1)<<1))-1;
    
    		int nx=getint(), ny=getint();
    		q[0].x=nx, q[0].y=ny;
    		int &f=q[0].f;
    		rep(i, l-1) {
    			int x=getint(), y=getint();
    			if(x==nx-1) f|=(1<<(i<<1));
    			else if(x==nx+1) f|=(0<<(i<<1));
    			else if(y==ny-1) f|=(3<<(i<<1));
    			else if(y==ny+1) f|=(2<<(i<<1));
    			nx=x; ny=y;
    		}
    		int k=getint();
    		while(k--) { int x=getint(), y=getint(); mp[x][y]=1; } 
    		bfs();
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    微信小程序HTTPS
    微信商城-1简介
    va_list
    Event log c++ sample.
    EVENT LOGGING
    Analyze Program Runtime Stack
    unknow table alarmtemp error when drop database (mysql)
    This application has request the Runtime to terminate it in an unusual way.
    How to check if Visual Studio 2005 SP1 is installed
    SetUnhandledExceptionFilter
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/3961673.html
Copyright © 2020-2023  润新知