noip28
东方专场?
T1
%%%WYZG
话说我考场上还想二维hash来着
考虑只记录弹幕中x的相对位置。
先选定弹幕一个点作为基准点(第一个出现的x即可),然后,枚举其他的x,记录下坐标差,然后去方格图中枚举,每找到一个x就去用坐标差计算出其他可能的x坐标,然后判断计算出的位置上是否有x,如果有,就消掉,下回不再枚举,没有,就说明不符合题目要求,输出No。
记得特判没有x的情况。
代码一些小细节可能没考虑到,但数据水,能过。
Code
#include<cstdio>
#define MAX 1010
#define re register
namespace OMA
{
int t,n,m,a,b;
struct node
{
int x,y;
}pair[MAX*MAX];
inline int read()
{
int s=0,w=1; char ch=getchar();
while(ch<'0'||ch>'9'){ if(ch=='-')w=-1; ch=getchar(); }
while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); }
return s*w;
}
signed main()
{
t = read();
while(t--)
{
bool flag1 = false;
char s1[MAX][MAX],s2[MAX][MAX];
n = read(),m = read(),a = read(),b = read();
for(re int i=1; i<=n; i++)
{
scanf("%s",s1[i]+1);
if(!flag1)
{
for(re int j=1; j<=m; j++)
{ if(s1[i][j]=='x'){ flag1 = true; break ; } }
}
}
bool flag2 = true;
int cnt = 0,x1 = 0,y1 = 0;
for(re int i=1; i<=a; i++)
{
scanf("%s",s2[i]+1);
if(flag2)
{
for(re int j=1; j<=b; j++)
{
if(s2[i][j]=='x')
{ x1 = i,y1 = j,flag2 = false; break ; }
}
}
}
if((!x1||!y1)&&flag1)
{ printf("No\n"); continue ; }
if((!x1||!y1)&&!flag1)
{ printf("Yes\n"); continue ; }
for(re int i=1; i<=a; i++)
{
for(re int j=1; j<=b; j++)
{
if(s2[i][j]=='x')
{
if(i==x1&&j==y1)
{ continue ; }
pair[++cnt] = (node){i-x1,j-y1};
}
}
}
flag1 = true;
for(re int i=1; i<=n; i++)
{
for(re int j=1; j<=m; j++)
{
if(s1[i][j]=='x')
{
s1[i][j]=='.';
for(re int k=1; k<=cnt; k++)
{
if(s1[i+pair[k].x][j+pair[k].y]!='x')
{ printf("No\n"); flag1 = false; break ; }
s1[i+pair[k].x][j+pair[k].y] = '.';
}
}
if(!flag1)
{ break ; }
}
if(!flag1)
{ break ; }
}
if(flag1)
{ printf("Yes\n"); }
}
return 0;
}
}
signed main()
{ return OMA::main(); }
T2
又又又读题死亡,奇数位置指的是位置的编号,不是坐标大小。
小球进洞模型,然而我都不知道有这玩意
考虑dp,设 \(dp_{n,i}\) 表示给定 \(n\)时 ,\(x_{i}-x_{i-1}\) 的贡献,转移时枚举第一次选了那个球,它往那边滚了,直接转移 \(O(n^{3})\)。
实际上我们并不需要枚举它往那边滚了,第一次选的球只有在 “i的旁边” 和 “不在i的旁边” 两种。所以复杂度 \(O(n^{2})\) 可过。
附80pts直接转移code
Code
#include<cstdio>
#define MAX 3100
#define re register
#define int long long
namespace OMA
{
int n,x[MAX<<1],ans;
int dp[MAX][MAX<<1];
const int p = 998244353;
inline int read()
{
int s=0,w=1; char ch=getchar();
while(ch<'0'||ch>'9'){ if(ch=='-')w=-1; ch=getchar(); }
while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); }
return s*w;
}
inline int quickpow(int a,int b)
{
int ans = 1;
while(b)
{
if(b&1)
{ ans = ans*a%p; }
a = a*a%p;
b >>= 1;
}
return ans;
}
signed main()
{
n = read();
for(re int i=1; i<=n*2+1; i++)
{ x[i] = read(); }
for(re int i=1; i<=n; i++)
{
int inv1 = quickpow(i,p-2),inv2 = quickpow(i*2,p-2);
for(re int j=2; j<=2*i+1; j++)
{
int calc = (i*2-j+1)/2;
if(j&1)
{ (dp[i][j] += dp[i-1][j-2]%p*inv2%p) %= p; }
else
{ (dp[i][j] += dp[i-1][j]%p*inv2%p) %= p; }
(dp[i][j] += ((dp[i-1][j]*calc%p*inv1%p+dp[i-1][j-1]*inv2%p)%p+(i-calc-1)*dp[i-1][j-2]%p*inv1%p+inv2%p)) %= p;
/*for(re int k=1; k<=i; k++)
{
if(2*k>j)
{ (dp[i][j] += dp[i-1][j]*inv1%p) %= p; }
else if(2*k==j-1)
{ (dp[i][j] += dp[i-1][j-1]*inv2%p+dp[i-1][j-2]*inv2%p+inv2) %= p; }
else if(2*k<j)
{ (dp[i][j] += dp[i-1][j-2]*inv1%p) %= p; }
else
{ (dp[i][j] += dp[i-1][j]*inv2%p+dp[i-1][j-1]*inv2%p+inv2) %= p; }
}*/
}
}
for(re int i=2; i<=n*2+1; i++)
{ (ans += dp[n][i]*(x[i]-x[i-1])%p) %= p; /*printf("%lld\n",dp[n][i]);*/ }
printf("%lld\n",ans);
return 0;
}
}
signed main()
{ return OMA::main(); }
T3
注意到边的类型是单调变小的,考虑用两个并查集来维护边的种类,一个表示1类边,另一个表示1类边+2类边。
再维护需要经过3类边的点的个数,在维护修改时大力更新即可。
具体见代码。
初始化写锅调了好久QAQ
Code
#include<cstdio>
#define MAX 300010
#define re register
namespace OMA
{
int n,m,num[MAX];
struct graph
{
int next;
int to;
int w;
}edge[MAX<<1];
int cnt=1,head[MAX];
inline void add(int u,int v,int w)
{ edge[++cnt] = (graph){head[u],v,w},head[u] = cnt; }
struct DSU
{
int fa[MAX],size[MAX];
inline void start()
{
for(re int i=1; i<=n; i++)
{ fa[i] = i,size[i] = 1; }
}
inline int find(int x)
{ return x!=fa[x]?fa[x] = find(fa[x]):fa[x]; }
inline void merge(int x,int y)
{
int r1 = find(x),r2 = find(y);
if(r1!=r2)
{ fa[r1] = r2,size[r2] += size[r1]; }
}
}dsu1,dsu2;
int fa[MAX],sta[MAX];
inline void dfs(int u,int die,int state)
{
fa[u] = die,sta[u] = state;
for(re int i=head[u],v; i; i=edge[i].next)
{
v = edge[i].to;
if(v!=die)
{ dfs(v,u,edge[i].w); }
}
}
struct stream
{
template<typename type>inline stream &operator >>(type &s)
{
int w=1; s=0; char ch=getchar();
while(ch<'0'||ch>'9'){ if(ch=='-')w=-1; ch=getchar(); }
while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); }
return s*=w,*this;
}
}cin;
inline void swap(int &a,int &b)
{ int t=a; a=b; b=t; }
signed main()
{
cin >> n >> m;
for(re int i=1,u,v,w; i<=n-1; i++)
{ cin >> u >> v >> w; add(u,v,w),add(v,u,w); }
dfs(1,0,0);
dsu1.start(),dsu2.start();
for(re int i=1; i<=n; i++)
{
if(sta[i]==1)
{ dsu1.merge(i,fa[i]); }
if(sta[i]!=3)
{ dsu2.merge(i,fa[i]); }
}
for(re int i=1; i<=n; i++)
{
if(sta[i]==3)
{ num[dsu1.find(fa[i])] += dsu2.size[i]; }
}
//for(re int i=1; i<=n; i++)
//{ printf("sta[%d]=%d,num[%d]=%d %d %d\n",i,sta[i],i,num[i],dsu1.size[i],dsu2.size[i]); }
for(re int i=1,a,b,s,t; i<=m; i++)
{
cin >> a >> b >> s >> t;
if(fa[a]==b)
{ swap(a,b); }
if(sta[b]==2)
{
num[dsu1.find(a)] += num[b];
dsu1.merge(b,a);
}
if(sta[b]==3)
{
num[dsu1.find(a)] -= dsu2.size[b];
num[dsu1.find(fa[dsu2.find(a)])] += dsu2.size[b];
dsu2.merge(b,a);
}
if(sta[b]!=1)
{ sta[b]--; }
bool flag = false;
if(dsu2.find(s)==dsu2.find(t))
{ flag = true; }
if(dsu1.find(s)==dsu1.find(fa[dsu2.find(t)]))
{ flag = true; }
if(dsu2.find(fa[dsu1.find(s)])==dsu2.find(t))
{ flag = true; }
int ans = num[dsu1.find(s)]+dsu2.size[dsu2.find(s)];
if(sta[dsu1.find(s)]==3)
{ ans += dsu2.size[dsu2.find(fa[dsu1.find(s)])]; }
printf("%d %d\n",flag?1:0,ans);
}
return 0;
}
}
signed main()
{ return OMA::main(); }
noip28的更多相关文章
随机推荐
- Louvain 论文笔记
Louvain Introduce Louvain算法是社区发现领域中经典的基于模块度最优化的方法,且是目前市场上最常用的社区发现算法.社区发现旨在发现图结构中存在的类簇(而非传统的向量空间). Al ...
- ARTS第一周
开始进行的第一周. 1.Algorithm:每周至少做一个 leetcode 的算法题2.Review:阅读并点评至少一篇英文技术文章3.Tip:学习至少一个技术技巧4.Share:分享一篇有观点和思 ...
- 「CF643G」 Choosing Ads
「CF643G」 Choosing Ads 传送门 如果你知道摩尔投票法可以扩展事实上是个一眼题,又好写又好调. 首先摩尔投票法是用来求众数定义为超过所有数个数一半的数的一个算法. 大致算法流程: 将 ...
- YAOI Round #1 题解
前言 比赛网址:http://47.110.12.131:9016/contest/3 总体来说,这次比赛是有一定区分度的, \(\text{ACM}\) 赛制也挺有意思的. 题解 A. 云之彼端,约 ...
- shell脚本编写规范和相关变量类型
shell编程规范与变量 一.shell脚本概述 ① 什么是shell? Linux中有哪些shell? ② shell的作用 ③ 用户的登录shell ④ shell脚本 ...
- c语言:逗号运算符
#include <stdio.h> main() { int a,s,d; s=2,d=3; a=12+(s+2,d+4); printf("%d\n",a); in ...
- [002] - JavaSE面试题(二):基本数据类型与访问修饰符
第一期:Java面试 - 100题,梳理各大网站优秀面试题.大家可以跟着我一起来刷刷Java理论知识 [002] - JavaSE面试题(二):基本数据类型与访问修饰符 第1问:Java的数据类型有哪 ...
- js学习-es6实现枚举
最近大部分时间再写dart,突然用到js,发现js不能直接声明一个枚举.搜索发现还是有实现的方式,于是总结一下. 目录 枚举特点 Object.freeze() Symbol 实现 体现不可更改 体现 ...
- NDT匹配: The Normal Distributions Transform: A New Approach to Laser Scan
介绍 大多数激光匹配算法都是基于点或者线的特征匹配,该论文提出一种2D激光扫描匹配算法,方法类似于占据栅格,将2D平面分为一个个cell,对于每个cell,设定其一个正态分布,表示该网格测量到每个点的 ...
- Spring最简单构建一个后台{msg:"登录成功",code:200,data:null}
一.简介 {msg:"登录成功",code:200,data:null} 二.两种请求 如果严格msg code data也带"" @RestControlle ...