Contest14的本质:区间覆盖+Tarjan(

A

把距离公式两边平方即可

注意要long long

code

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
using namespace std; int x[100001];
int y[100001];
int n,i,j,k,l,X,Y,R,ans; int main()
{
// freopen("a.in","r",stdin); scanf("%d%d%d%d",&n,&X,&Y,&R);
fo(i,1,n)
scanf("%d%d",&x[i],&y[i]); fo(i,1,n)
if (((long long)(x[i]-X)*(x[i]-X)+(long long)(y[i]-Y)*(y[i]-Y))<=(long long)R*R)
++ans; printf("%d\n",ans);
}

B

显然p和k是位置最靠边的两个

考虑一下i和n的位置(靠左/靠右/左右)

code

比较丑

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define max(a,b) (a>b?a:b)
using namespace std; char a[1000001];
int T,n,i,j,k,l,ans,s1,s2,s3,s4;
char ch; int main()
{
// freopen("b.in","r",stdin); scanf("%d",&T);
for (;T;--T)
{
ans=-1;
scanf("%d",&n); fo(i,1,n)
{
ch=getchar();
while (ch<'a' || ch>'z')
ch=getchar(); a[i]=ch;
} fo(i,1,n)
if (a[i]=='p')
break; fd(j,n,1)
if (a[j]=='k')
break; fo(k,i+1,n)
if (a[k]=='i')
break; fo(l,k+1,n)
if (a[l]=='n')
break;
if (i>=1 && i<k && k<l && l<j && j<=n && a[i]=='p' && a[k]=='i' && a[l]=='n' && a[j]=='k')
ans=max(ans,max(max(k-i-1,l-k-1),j-l-1)); fd(l,j-1,k+1)
if (a[l]=='n')
break;
if (i>=1 && i<k && k<l && l<j && j<=n && a[i]=='p' && a[k]=='i' && a[l]=='n' && a[j]=='k')
ans=max(ans,max(max(k-i-1,l-k-1),j-l-1)); fd(l,j-1,1)
if (a[l]=='n')
break;
fd(k,l-1,i+1)
if (a[k]=='i')
break;
if (i>=1 && i<k && k<l && l<j && j<=n && a[i]=='p' && a[k]=='i' && a[l]=='n' && a[j]=='k')
ans=max(ans,max(max(k-i-1,l-k-1),j-l-1)); printf("%d\n",ans);
}
}

C

区间覆盖*1

一开始以为一对区间只能算一次答案

维护断点,那么一种方案=断点数-1(加上首尾)

一次覆盖后,区间外的不变,区间内的变为0,边界变为1

所以可以合在一起维护,区间外的*2,区间内的不变,边界+2^(i-1)

i的答案为断点总数-2^i

code

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define mod 20050321
using namespace std; long long p[2001];
int L[2001];
int R[2001];
bool b[2001];
long long sum[2001];
long long Sum[2001];
int n,m,i,j,k,l;
long long ans; int main()
{
// freopen("c.in","r",stdin); scanf("%d%d",&n,&m);
p[0]=1;
fo(i,1,m)
{
scanf("%d%d",&L[i],&R[i]);
p[i]=p[i-1]*2%mod;
} sum[0]=sum[n]=1;
fo(i,1,m)
{
fo(j,0,n) Sum[j]=sum[j];
fo(j,0,L[i]-2) Sum[j]=(Sum[j]+sum[j])%mod;
fo(j,R[i]+1,n) Sum[j]=(Sum[j]+sum[j])%mod;
Sum[L[i]-1]=(Sum[L[i]-1]+p[i-1])%mod;
Sum[R[i]]=(Sum[R[i]]+p[i-1])%mod; ans=0;
fo(j,0,n)
sum[j]=Sum[j],Sum[j]=0,ans=(ans+sum[j])%mod; printf("%lld\n",(ans-p[i]+mod)%mod);
}
}

D

区间覆盖*2

套路,询问若一段操作的结果就把询问离线按r排序,每次加一个操作计算答案

维护每一段区间的两个端点(左右括号),那么每加一个区间最多加4个括号,每个括号只会被删一次

每加一个区间,就相当于把中间的端点删掉(大的能覆盖掉小的),再在两边加上新的端点

询问就是求每个修改所剩余的个数*权值的后缀和

用set维护括号,每次断开后找中间的区间,用树状数组维护答案

code

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <set>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define low(x) (x&-(x))
using namespace std; struct qs{
int l,r,id;
} q[500001];
struct type{
int x,s,t; //0=right 1=left
bool friend operator < (type a,type b) {return a.x<b.x || a.x==b.x && a.t<b.t;}
};
int a[500001][3];
long long ans[500001];
long long tr[500001];
multiset<type> st;
multiset<type> :: iterator I,J;
int n,m,Q,i,j,k,l; bool cmp(qs a,qs b)
{
return a.r<b.r;
} void change(int t,long long s)
{
while (t<=n)
{
tr[t]+=s;
t+=low(t);
}
}
long long find(int t)
{
long long ans=0; while (t)
{
ans+=tr[t];
t-=low(t);
} return ans;
} int main()
{
// freopen("d.in","r",stdin); scanf("%d%d%d",&n,&m,&Q);
fo(i,1,n)
scanf("%d%d%d",&a[i][0],&a[i][1],&a[i][2]);
fo(i,1,Q)
scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i; sort(q+1,q+Q+1,cmp); st.insert({0,0,1});
st.insert({m,0,0});
fo(i,1,Q)
{
fo(j,q[i-1].r+1,q[i].r)
{
I=st.lower_bound({a[j][0]-1,0,1});
if (I!=st.begin())
{
--I;
if ((*I).x<a[j][0]-1)
{
k=(*I).s;
st.insert({a[j][0]-1,k,0});
st.insert({a[j][0]-1,k,1});
}
} I=st.upper_bound({a[j][1],0,0});
if (I!=st.end())
{
if (a[j][1]<(*I).x)
{
k=(*I).s;
st.insert({a[j][1],k,0});
st.insert({a[j][1],k,1});
}
} I=st.lower_bound({a[j][0]-1,0,1});
J=st.upper_bound({(*I).x,0,1});
while (I!=st.end() && (*I).x<a[j][1])
{
if ((*I).s)
change((*I).s,-(long long)a[(*I).s][2]*((*J).x-(*I).x)); st.erase(I);
J=st.lower_bound({a[j][0]-1,0,1});
st.erase(J); I=st.lower_bound({a[j][0]-1,0,1});
J=st.upper_bound({(*I).x,0,1});
} st.insert({a[j][0]-1,j,1});
st.insert({a[j][1],j,0});
change(j,(long long)a[j][2]*(a[j][1]-a[j][0]+1));
} ans[q[i].id]=find(q[i].r)-find(q[i].l-1);
} fo(i,1,Q)
printf("%lld\n",ans[i]);
}

E

Tarjan*1

这应该是除了那道简单数论以外最水的E了

Tarjan缩强联通分量,dp维护从起点到每个点的最小边权、最大边权、最大差值

正确性:最大差值与路径上的最大&最小值有关,那么一定会在找到后面那个(大or小)的时候与另一个计算到

注意细节,考虑极值所在位置(原点、边、新点)

code

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
using namespace std; int a[500001][3];
int ls[200001];
int A[500001][3];
int Ls[200001];
int dfn[200001];
int low[200001];
int d[200001];
int D[200001];
int mx[200001];
int mn[200001];
bool bz[200001];
int num[200001];
int f[200001][3]; //mn,mx,ans
int n,m,Q,i,j,k,l,len,Len,tot,h,t; void New(int x,int y,int z)
{
++len;
a[len][0]=y;
a[len][1]=ls[x];
ls[x]=len;
a[len][2]=z;
}
void NEW(int x,int y,int z)
{
++Len;
A[Len][0]=y;
A[Len][1]=Ls[x];
Ls[x]=Len;
A[Len][2]=z; ++D[y];
} void dfs(int t)
{
int i; ++j;
dfn[t]=j;
low[t]=j;
bz[t]=1;
d[++l]=t; for (i=ls[t]; i; i=a[i][1])
{
if (!dfn[a[i][0]])
{
dfs(a[i][0]);
low[t]=min(low[t],low[a[i][0]]);
}
else
if (bz[a[i][0]])
low[t]=min(low[t],dfn[a[i][0]]);
} if (dfn[t]==low[t])
{
++tot;
while (d[l]!=t)
{
bz[d[l]]=0;
num[d[l--]]=tot;
}
bz[d[l]]=0;
num[d[l--]]=tot;
}
} int main()
{
// freopen("e.in","r",stdin);
// freopen("b.out","w",stdout); scanf("%d%d%d",&n,&m,&Q);
fo(i,1,m)
{
scanf("%d%d%d",&j,&k,&l);
New(j,k,l);
} memset(mx,190,sizeof(mx));
memset(mn,60,sizeof(mn));
j=l=0;
dfs(1); fo(j,1,n)
if (num[j])
{
for (i=ls[j]; i; i=a[i][1])
if (num[a[i][0]])
{
if (num[j]==num[a[i][0]])
{
mx[num[j]]=max(mx[num[j]],a[i][2]);
mn[num[j]]=min(mn[num[j]],a[i][2]);
}
else
NEW(num[j],num[a[i][0]],a[i][2]);
}
} h=t=0;
fo(i,1,tot)
if (!D[i])
d[++t]=i; fo(i,1,tot)
{
f[i][0]=mn[i];
f[i][1]=mx[i];
f[i][2]=f[i][1]-f[i][0];
}
while (h<t)
{
for (i=Ls[d[++h]]; i; i=A[i][1])
{
f[A[i][0]][0]=min(f[A[i][0]][0],min(f[d[h]][0],A[i][2]));
f[A[i][0]][1]=max(f[A[i][0]][1],max(f[d[h]][1],A[i][2])); f[A[i][0]][2]=max(f[A[i][0]][2],A[i][2]-f[d[h]][0]);
f[A[i][0]][2]=max(f[A[i][0]][2],mx[A[i][0]]-f[d[h]][0]);
f[A[i][0]][2]=max(f[A[i][0]][2],mx[A[i][0]]-A[i][2]); f[A[i][0]][2]=max(f[A[i][0]][2],f[d[h]][1]-A[i][2]);
f[A[i][0]][2]=max(f[A[i][0]][2],f[d[h]][1]-mn[A[i][0]]);
f[A[i][0]][2]=max(f[A[i][0]][2],A[i][2]-mn[A[i][0]]); f[A[i][0]][2]=max(f[A[i][0]][2],max(f[d[h]][2],0)); --D[A[i][0]];
if (!D[A[i][0]])
d[++t]=A[i][0];
}
} for (;Q;--Q)
{
scanf("%d",&j);
if (num[j] && f[num[j]][2]>=0)
printf("%d\n",f[num[j]][2]);
else
printf("-1\n");
}
}

F

Tarjan*2

显然可以求出相交关系然后求割点,用主席树优化连边

口胡一下

按横/竖顺序扫描线,考虑相交线段a和b

a在加入时由叶子连向a,b在查找时由b连向询问区间

每个区间向儿子连边,询问时新建叶节点时就向原叶节点连边,如果是删除一段线段就不连

一次修改or询问的操作节点和连边数为log n级别

两种顺序搞完之后Tarjan求割点即可

code

没写

Comet OJ - Contest #14题解的更多相关文章

  1. Comet OJ - Contest #11 题解&赛后总结

    Solution of Comet OJ - Contest #11 A.eon -Problem designed by Starria- 在模 10 意义下,答案变为最大数的最低位(即原数数位的最 ...

  2. Comet OJ - Contest #0题解

    传送门 菜爆了--总共只有一道题会做的--而且也没有短裙好难过 为啥必须得有手机才能注册账号啊喂--歧视么-- \(A\) 解方程 推一下柿子大概就是 \[x-\sqrt{n}=y+z+2\sqrt{ ...

  3. Comet OJ - Contest #3 题解

    传送门 太菜了连\(D\)都做不出来没有小裙子\(QAQ\) \(A\) 暴力把所有的数对都算出来,然后\(sort\)一下就行了 const int N=505; int a[N],st[N*N], ...

  4. Comet OJ - Contest #2题解

    传送门 既然没参加过就没有什么小裙子不小裙子的了-- 顺便全是概率期望真是劲啊-- 因自过去而至的残响起舞 \(k\)增长非常快,大力模拟一下就行了 int main(){ scanf("% ...

  5. Comet OJ - Contest #15 题解

    传送门 \(A\) 咕咕 const int N=1005; int a[N],n,T; int main(){ for(scanf("%d",&T);T;--T){ sc ...

  6. Comet OJ - Contest #14 转转的数据结构题 珂朵莉树+树状数组

    题目链接: 题意:有两个操作 操作1:给出n个操作,将区间为l到r的数字改为x 操作2:给出q个操作,输出进行了操作1中的第x到x+y-1操作后的结果 解法: 把询问离线,按照r从小到大排序 每次询问 ...

  7. Comet OJ - Contest #11题解

    传送门 \(A\) 咕咕咕 const int N=1e6+5; char s[N],t[N];int n,res; inline bool cmp(const int &x,const in ...

  8. Comet OJ - Contest #8题解

    传送门 \(A\) 咕咕咕 const int N=1005; char s[N][N];int len[N],n,id; inline bool cmp(R int j,R int k){ R in ...

  9. Comet OJ - Contest #14

    Rank38. 还是比较不满意吧,C卡了太久,E没调出来,D也没空去做了. A 签到题. #include<bits/stdc++.h> using namespace std; #def ...

随机推荐

  1. P3611 【[USACO17JAN]Cow Dance Show奶牛舞蹈】

    想了一下还是不发以前做过的水题了,意义也不是很大,现在的话大概只有洛谷黄题以上才会收录了哦~~~ 喵了个咪的题面~~ 洛谷题解dalao不是P党就是优先队列,看的我作为一个新手蒟蒻好慌啊... 这题用 ...

  2. 前端,后端,UI,UE,UX,区别到底在哪里?

    前端后端,到低区别在哪里? 其实后端是负责更为复杂的数据逻辑,表处理结构,如何实现一连串的数据提交,包括,数据验证,数据影响,数据计算,数据提取,,,等等. 那么前端负责的是什么呢?数据展示,数据验证 ...

  3. https原理以及golang基本实现

    关于https 背景知识 密码学的一些基本知识 大致上分为两类,基于key的加密算法与不基于key的加密算法.现在的算法基本都是基于key的,key就以一串随机数数,更换了key之后,算法还可以继续使 ...

  4. 2019JAVA第十一次实验报告

    #Java实验报告 班级 计科二班 学号 20188442 姓名 吴怡君 完成时间 2019.11.22 评分等级 简易记事本 实验代码 package Domon10; import java.aw ...

  5. [百度知道]ssm和ssh各自的优势

    https://zhidao.baidu.com/question/875108451824176892.html SSM和SSH不同主要在MVC实现方式,以及ORM持久化方面不同(Hiibernat ...

  6. 洛谷 P3857 彩灯 题解

    题面 对于每一个开关,我们可以看成一个0/1串,初始是一个全部为0的串,要求经过这些开关的操作后,出现的不同的0/1串的个数 建模就是存在一些数,这些数异或起来是0(等价于没有操作).那么需要求一个集 ...

  7. CF1142B Lynyrd Skynyrd

    题目 有两种做法: 第一种是\(O(nlog\ n)\)的. 我们预处理两个数组: \(pre_i\)表示\(p\)中\(i\)前面的那个数是\(pre_i\). \(lst_i\)表示\(a\)中\ ...

  8. linux复习4:文件和目录

    7一.linux文件 1.linux文件的扩展名:文件扩展名是文件名最后一个点之后的部分,下面列出了其中一部分 (1)压缩文件和归档文件 压缩和归档的文件扩展名及其含义如下. .bz2:使用bzip2 ...

  9. yii报错yii\web\Request::cookieValidationKey must be configured with a secret key.

    在config文件下main-local.php配置 'cookieValidationKey' => 'rabbit1234',

  10. vue单页应用中根据不同城市不同业务添加百度统计代码

    问题描述: 我们知道一般的百度统计代码是添加在html的head里的:但是,因为目前项目是用vue开发的单页应用,所以在路由跳转之间不会刷新页面, 统计代码如果放在项目里的index.heml的hea ...