Educational Codeforces Round 138 (Rated for Div. 2)
我模拟了一遍,因为我没看到题目中给出的矩阵已经合法,
实验室同事跟我说只要判断
int x[N],y[N],m,n;
bool check(){
for(int i=1;i<=m;i++){
for(int j=1;j<=m;j++){
if(i==j)continue;
if(x[i]==x[j]||y[i]==y[j])return false;
}
}
return true;
}
void solve(){
n=read(),m=read();
int ans=0;
for(int i=1;i<=m;i++){
x[i]=read();
y[i]=read();
}
for(int i=1;i<=m;i++){
int tx=x[i],ty=y[i];
for(int j=1;j<=n;j++){
if(j==ty)continue;
x[i]=tx;
y[i]=j;
if(check())ans=1;
}
for(int j=1;j<=n;j++){
if(j==tx)continue;
x[i]=j;
y[i]=ty;
if(check())ans=1;
}
x[i]=tx;
y[i]=ty;
}
puts(ans==1?"YES":"NO");
//puts(ans>0?"Yes":"No");
}
看了下题,感觉每次删掉前面和后面更小的一个就行了。
要从中间删会被计算两次,而头尾只会被计算一次。因为最后只会剩下一个数,所以可以让最大的数留下来。
void solve(){
int n=read(),sum=0;
for(int i=1;i<=n;i++){
sum+=read();
}
deque<int>a;
for(int i=1;i<=n;i++){
a.push_back(read());
}
for(int i=1;i<n;i++){
if(a.front()<=a.back()){
sum+=a.front();
a.pop_front();
}else{
sum+=a.back();
a.pop_back();
}
}
cout<<sum<<'\n';
//puts(ans>0?"YES":"NO");
//puts(ans>0?"Yes":"No");
}
本题可以用二分答案,在
void solve(){
int n=read(),ans=0;
multiset<int>st;
for(int i=1;i<=n;i++){
st.insert(read());
}
for(int k=1;k<=n;k++){
multiset<int>tp(st);
int ok=1;
for(int i=1;i<=k;i++){
int x=k-i+1;
while(tp.upper_bound(x)!=tp.end())
tp.erase(tp.upper_bound(x));
if(tp.size()==0){
ok=0;
break;
}
auto it=tp.upper_bound(x);
it--;
tp.erase(it);
if(tp.size()){
tp.erase(tp.begin());
}
x--;
}
if(ok)ans=k;
}
cout<<ans<<'\n';
//puts(ans>0?"YES":"NO");
//puts(ans>0?"Yes":"No");
}
思考什么样的数列会是
int primes[N], cnt;
bool st[N];
void get_primes(int n){
for (int i = 2; i <= n; i ++ ){
if (!st[i]) primes[cnt ++ ] = i;
for (int j = 0; primes[j] <= n / i; j ++ ){
st[primes[j] * i] = true;
if (i % primes[j] == 0) break;
}
}
}
int fac[N];
void init(){
get_primes(N-1);
fac[1]=1;
for(int i=2;i<N;i++){
fac[i]=fac[i-1];
if(!st[i])fac[i]*=i;
// fac[i]=mod;
}
}
void solve(){
int n=read(),m=read();
mint tol=0,ans=1,sum=1;
for(int i=1;i<=n;i++){
sum*=m;
ans*=(m/fac[i]);
tol+=sum-ans;
}
cout<<tol<<'\n';
//puts(ans>0?"YES":"NO");
//puts(ans>0?"Yes":"No");
}
那么转换题意,就是要求一条从左边到右边可以横穿的仙人掌路,而且路还得斜着走。那么对于已经有仙人掌的点点权记为
struct node{
int x,y;
};
const int dx[]={0,0,1,-1,1,1,-1,-1};
const int dy[]={1,-1,0,0,1,-1,1,-1};
deque<node>q;
vector<int>pre[N],d[N];
string mp[N];
int n,m;
bool check(int x,int y){
if(x<0||x>=n||y<0||y>=m)return false;
for(int i=0;i<4;i++){
int xx=x+dx[i],yy=y+dy[i];
if(xx>=0&&xx<n&&yy>=0&&yy<m&&mp[xx][yy]=='#')return false;
}
return true;
}
void bfs(){
while(!q.empty()){
int x=q.front().x,y=q.front().y;
q.pop_front();
for(int i=4;i<8;i++){
int xx=x+dx[i],yy=y+dy[i];
if(!check(xx,yy))continue;
int s=(mp[xx][yy]=='.');
if(d[xx][yy]>d[x][y]+s){
d[xx][yy]=d[x][y]+s;
pre[xx][yy]=i;
if(s)q.push_back((node){xx,yy});
else q.push_front((node){xx,yy});
}
}
}
}
void solve(){
n=read(),m=read();
for(int i=0;i<n;i++){
cin>>mp[i];
}
for(int i=0;i<n;i++){
pre[i].clear();
d[i].clear();
for(int j=0;j<m;j++){
d[i].push_back(inf);
pre[i].push_back(0);
}
if(mp[i][0]=='#')q.push_front((node){i,0}),d[i][0]=0;
else if(check(i,0))q.push_back((node){i,0}),d[i][0]=1;
}
bfs();
int minn=inf,mini=-1;
for(int i=0;i<n;i++){
if(d[i][m-1]<minn){
minn=d[i][m-1];
mini=i;
}
}
if(mini==-1){
cout<<"NO\n";
return ;
}
cout<<"YES\n";
int x=mini,y=m-1;
while(1){
mp[x][y]='#';
if(!pre[x][y])break;
int lst=pre[x][y];
x-=dx[lst];y-=dy[lst];
}
for(int i=0;i<n;i++){
cout<<mp[i]<<'\n';
}
//puts(ans>0?"YES":"NO");
//puts(ans>0?"Yes":"No");
}
对于修改操作可以先对路径标记,用树状数组
子树内修改为
vector<int>adj[N+5];
int f[N+5][21],n,m;
int son[N+5],siz[N+5],father[N+5],top[N+5],in[N+5],out[N+5],dep[N+5],timer;
struct Fenwick {
int c[N+5];
inline int lowbit(int x) {return x&(-x);}
inline void add(int x,int d) {
for(;x<=n;x+=lowbit(x))c[x]+=d;
}
inline int query(int x) {
int res=0;
for(;x>=1;x-=lowbit(x))res+=c[x];
return res;
}
inline int rangequery(int l,int r) {
return query(r)-query(l-1);
}
}fen[21];
void dfs1(int u,int fa) {
siz[u]=1,father[u]=fa,dep[u]=dep[fa]+1;
int mx=0;
for(int v:adj[u])
if(v!=fa) {
dfs1(v,u);
if(siz[v]>mx)son[u]=v,mx=siz[v];
siz[u]+=siz[v];
}
}
void dfs2(int u,int fa,int now) {
top[u]=now,in[u]=++timer;
if(son[u])dfs2(son[u],u,now);
for(int v:adj[u])
if(v!=son[u]&&v!=fa)dfs2(v,u,v);
out[u]=timer;
}
inline int lca(int x,int y) {
while(top[x]!=top[y]) {
if(dep[top[x]]<dep[top[y]])swap(x,y);
x=father[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
return x;
}
inline void modify(int x,int y,int k,int d) {
int z=lca(x,y);
fen[k].add(in[x],d);
fen[k].add(in[y],d);
fen[k].add(in[z],-2*d);
for(int i=0;i<=k&&z;i++) {
f[z][k-i]+=d;
if(k-i-2>=0&&z!=1)f[z][k-i-2]-=d;
z=father[z];
}
}
inline int query(int x) {
int res=0,dis=0;
for(int i=0;i<=20&&x;i++) {
res+=fen[i].rangequery(in[x],out[x]);
for(int j=dis;j<=20;j++)res+=f[x][j];
++dis,x=father[x];
}
return res;
}
void solve() {
n=read();
for(int i=1;i<n;i++) { //build edge
int x=read(),y=read();
adj[x].push_back(y);
adj[y].push_back(x);
}
dfs1(1,0),dfs2(1,0,1); //build lca
m=read();
while(m--) {
int op=read();
if(op==1) {
int x=read();
cout<<query(x)<<'\n';
}
else {
int x=read(),y=read(),d=read(),k=read(); //distance is k add d
modify(x,y,k,d);
}
}
}
本文作者:EdGrass
本文链接:https://www.cnblogs.com/edgrass/p/17686188.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步