1104 DAN
D
多打一个0 爆空间 然后就掉50....
A 妹子
计算几何 斜挂了...
万人迷皮皮轩收到了很多妹子的礼物,由于皮皮轩觉得每个妹子都不错,所以将她们礼物
的包装盒都好好保存,但长此以往皮皮轩的房间里都堆不下了,所以只能考虑将一些包装盒
放
进其他包装盒里节省空间。
方便起见,我们不考虑包装盒的高度和厚度,只考虑包装盒的长宽。
一句话题意:给出两个矩形,问是否可以将一个矩形放在另一个矩形的内部(含边界),多
测
考试的时候找的条件不是充要条件....
按照面积进行讨论 枚举角度然后看算出来的长和宽是否小于就行了
//
#include<bits/stdc++.h>
using namespace std;
#define GC getchar()
int n,a1,b1,a2,b2;
double eps=0.001111;
inline int R() {
char t;
int x=0;
while(!isdigit(t)) {
t=GC;
}
while(isdigit(t)) {
x=x*10+t-48;
t=GC;
}
return x;
}
void FIE() {
freopen("girls.in","r",stdin);
freopen("girls.out","w",stdout);
}
int main() {
//FIE();
n=R();
while(n--) {
a1=R();
b1=R();
a2=R();
b2=R();
if(a1*b1>a2*b2) {
int fla=0;
for(double mid=0; (mid<=90)&&(!fla); mid+=0.0005) {
double c=cos(((double)mid/180*3.14159));
double s=sin(((double)mid/180*3.14159));
double x1=b2*s;
double x2=a2*c;
double y1=b2*c;
double y2=a2*s;
if((((b1-(x1+x2))>=0)&&(a1-(y1+y2))>=0)) {
puts("Yes");
fla=1;
continue;
}
}
if(fla) continue;
puts("No");
} else {
int fla=0;
for(double mid=0; (mid<=90)&&(!fla); mid+=0.0005) {
double c=cos(((double)mid/180*3.14159));
double s=sin(((double)mid/180*3.14159));
double x1=b1*s;
double x2=a1*c;
double y1=b1*c;
double y2=a1*s;
if((((b2-(x1+x2))>=0)&&(a2-(y1+y2))>=0)) {
puts("Yes");
fla=1;
continue;
}
}
if(fla) continue;
puts("No");
}
}
}
B
贪心贪错了 还掉了50
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
B 老大
题意同 Dynamite 这道题目 。。。。 我考试的时候巨贪 想贪心去了 .... 做过的题啊...
定义F1[i] 表示离i号根节点最近的未盖点 F2[i] 表示 离i号根节点最近的已被覆盖的点
DP一下即可
//
#include<bits/stdc++.h>
using namespace std;
#define maxnn (int)4e5+10
int las[maxnn],en[maxnn],nex[maxnn],tot;
int n;
int f1[maxnn],f2[maxnn];
#define GC getchar()
inline int R() {
char t;
int x=0;
while(!isdigit(t)) {
t=GC;
}
while(isdigit(t)) {
x=x*10+t-48;
t=GC;
}
return x;
}
int ans=0;
int size[maxnn];
void add(int a,int b ) {
en[++tot]=b;
nex[tot]=las[a];
las[a]=tot;
}
void TREE_DP(int v,int fa,int mid) {
for(int i=las[v]; i; i=nex[i]) {
int u=en[i];
if(u!=fa) {
TREE_DP(u,v,mid);
f1[v]=max(f1[v],f1[u]+1);
if(f2[u]!=-1) {
if(f2[v]==-1)
f2[v]=f2[u]+1;
else
f2[v]=min(f2[v],f2[u]+1);
}
}
}
if((f1[v]>=mid)) {
ans++;
f1[v]=-1;
f2[v]=0;
return ;
}
if(f2[v]>=0)
if((f1[v]<mid)&&(f1[v]<=(mid-f2[v]))) {
f1[v]=-1;
return ;
}
if(f1[v]==-1)
f1[v]=0;
}
int ch(int t) {
ans=0;
for(int i=1; i<=n; i++) {
f1[i]=f2[i]=-1;
}
TREE_DP(1,1,t);
if(f1[1]>=0) ans++;
return ans;
}
int main() {
int x,y;
n=R();
for(int i=1; i<n; i++) {
x=R();
y=R();
add(x,y);
add(y,x);
}
int l=0,r=10000000;
while(l<=r) {
int mid=(l+r)/2;
if(ch(mid)<=2) {
r=mid-1;
} else {
l=mid+1;
}
}
cout<<l;
}
C 相交
题目描述
一棵大树下有 n 个巢穴,由 n-1 条双向道路连接,任意两个城市均可互相到达。
大树附近有两群蚂蚁,每天早上,第一群蚂蚁会派一只蚂蚁到这棵树下,并在第 a 个巢穴
到 第
b 个巢穴间的最短路径上的每个巢穴留下气味。每天傍晚,第二群蚂蚁会派一只蚂蚁到
这
棵树下,并侦查第 c 个巢穴到第 d 个巢穴间的最短路径上是否有蚂蚁留下的气味。
每天蚂蚁留下的气味会在当天深夜消失。
输入
第一行一个正整数 n,含义如题所示。
接下来 n-1 行,每行两个正整数 u,v,表示第 u 个巢穴和第 v 个巢穴间有一条双向道路。
接下来一行一个正整数 q,表示天数。
接下来 q 行,每行四个正整数 a,b,c,d,含义如题所示。
输出
q 行,每行一个字符串。
若第二群派出的蚂蚁侦查到蚂蚁留下的气味,则输出” YES” ,否则输出” NO”
解1:
显然用树链剖分+树状数组维护
20min 敲完还不用调试
//
#include<bits/stdc++.h>
using namespace std;
#define maxnn 301000
#define GC getchar()
int n;
int las[maxnn],en[maxnn],nex[maxnn],tot;
int son[maxnn];
int size[maxnn];
int f[maxnn];
int c1[maxnn],c2[maxnn];
int dep[maxnn];
int dfn[maxnn],low[maxnn],vii,topp[maxnn];
void add(int a,int b) {
en[++tot]=b;
nex[tot]=las[a];
las[a]=tot;
}
void dfs1(int v,int fa) {
dep[v]=dep[fa]+1;
size[v]=1;
f[v]=fa;
int maxson=-1;
for(int i=las[v]; i; i=nex[i]) {
int u=en[i];
if(u!=fa) {
dfs1(u,v);
size[v]+=size[u];
if(size[u]>maxson) {
son[v]=u;
maxson=size[u];
}
}
}
}
void dfs2(int v,int fa,int t) {
topp[v]=t;
dfn[v]=++vii;
if(son[v]) {
dfs2(son[v],v,t);
}
for(int i=las[v]; i; i=nex[i]) {
int u=en[i];
if(u==fa) continue;
if(u==son[v]) continue;
dfs2(u,v,u);
}
}
inline int R() {
char t;
int x=0;
while(!isdigit(t)) {
t=GC;
}
while(isdigit(t)) {
x=x*10+t-48;
t=GC;
}
return x;
}
#define lowbit(i) i&(-i)
void aaa(int x,int d) {
for(int i=x; i<=n+10000; i+=lowbit(i)) {
c1[i]+=d;
c2[i]+=x*d;
}
}
int get(int x) {
int ans=0;
for(int i=x; i; i-=lowbit(i)) {
ans+=c1[i]*(x+1);
ans-=c2[i];
}
return ans;
}
void zadd(int x,int y,int d) {
while(topp[x]!=topp[y]) {
if(dep[topp[x]]<dep[topp[y]]) swap(x,y);
aaa(dfn[topp[x]],d);
aaa(dfn[x]+1,-d);
x=f[topp[x]];
}
if(dep[x]<dep[y]) swap(x,y);
aaa(dfn[y],d);
aaa(dfn[x]+1,-d);
}
bool query(int x,int y) {
int ans=0;
while(topp[x]!=topp[y]) {
if(dep[topp[x]]<dep[topp[y]]) swap(x,y);
if(get(dfn[x])-get(dfn[topp[x]]-1)) return true;
x=f[topp[x]];
}
if(dep[x]<dep[y]) swap(x,y);
if(get(dfn[x])-get(dfn[y]-1)) return true;
return false;
}
void FIE()
{
freopen("inter.in","r",stdin);
freopen("inter.out","w",stdout);
}
int main() {
//FIE();
n=R();
int x,y;
for(int i=1; i<n; i++) {
x=R();
y=R();
add(x,y);
add(y,x);
}
dfs1(1,1);
dfs2(1,1,1);
int q;
q=R();
int a,b,c,d;
while(q--) {
a=R();
b=R();
c=R();
d=R();
zadd(a,b,1);
if(query(c,d)) {
puts("YES");
} else {
puts("NO");
}
zadd(a,b,-1);
}
}
解2 注意到两条链是否有相交的充要条件是一条链的LCA 在 另一条lian 的路径上 然后我们求端点到LCA 的路径长度 是否等于 端点的长度就行了
N 230pts
A 方差
展开柿子就行了 5min 搞完 注意快读的时候 要判断负数
B 分糖果
遇到困难应该想到熔池
定义f[i]表示前i的不相同的方案数
则柿子可熔池为 \(f[i]=\sum_j f[j]*min(a[j+1...i])*{(-1)^{i-j-1}}\)
考虑链转环 利用转环的方式 将首尾相同的方案贡献算出来就行了 注意利用单调zhan 优化
时间复杂度 O(n)
//
#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 1000000007
#define maxnn 10000000
ll n,a[maxnn];
ll f[maxnn];
ll mi=1000000000;
ll pos;
ll sum[maxnn];
struct node {
ll l,r,v,s;
};
stack<node> Q;
int main() {
// freopen("data.in","r",stdin);
// freopen("myp.out","w",stdout);
ll ans=0;
cin>>n;
for(int i=1; i<=n; i++) {
scanf("%lld",&a[i]);
if(a[i]<mi) {
mi=a[i];
pos=i;
}
a[i+n]=a[i];
}
for(int i=1; i<=n; i++) {
a[i]=a[pos+i-1];
}
ll tot=mod-a[1];
for(int i=1; i<=n; i++) {
if(i&1) f[i]=(((f[i]-tot)%mod+mod))%mod;
else f[i]=(((f[i]+tot)%mod+mod))%mod;
sum[i]=sum[i-1];
if(i&1) sum[i]=((sum[i]+f[i])%mod+mod)%mod;
else sum[i]=((sum[i]-f[i])%mod+mod)%mod;
int l=i-1;
while(Q.size()&&(Q.top().v>a[i+1])) {
tot=((tot-Q.top().s)%mod+mod)%mod;
Q.pop();
if(Q.size())
l=Q.top().r;
else
{
l=0;
}
}
ll s=(((sum[i]-sum[l])*a[i+1])%mod+mod)%mod;
Q.push(node {l+1,i,a[i+1],s});
tot=((tot+s)%mod+mod)%mod;
}
for(int i=2; i<=n; i++) {
if((n-i)&1) ans=((ans-f[i])%mod+mod)%mod;
else ans=((ans+f[i])%mod+mod)%mod;
}
cout<<(ans%mod+mod)%mod;
}
C
题目描述
给定一张n个点m 条边的无向图,现在想要把这张图定向。
有 p个限制条件,每个条件形如(x,y) ,表示在新的有向图当中, x要能够沿
着一些边走到 y。
现在请你求出,每条边的方向是否能够唯一确定。同时请给出这些能够唯一确定
的边的方向
解:
tarjan 求边双联通分量缩点搞成一个森林 然后差分就行了
注意判断连通性
//
#include<bits/stdc++.h>
using namespace std;
#define maxnn (int)(2e5+10)
int belong[maxnn];
int dfn[maxnn],low[maxnn];
int vii;
int scc;
int vis[maxnn];
int dep[maxnn];
int f[maxnn][20];
int fff[maxnn];
int gf(int v) {
return fff[v]==v?v:fff[v]=gf(fff[v]);
}
int cnt1[maxnn],cnt2[maxnn];
int tot=1,nex[maxnn],las[maxnn],en[maxnn];
int ztot,znex[maxnn],zlas[maxnn],zen[maxnn];
#define GC getchar()
inline int R() {
int f=1;
int x=0;
char t;
t=GC;
while(!isdigit(t)) {
if(t=='-') {
f=-1;
}
t=GC;
}
while(isdigit(t)) {
x=x*10+t-48;
t=GC;
}
return x*f;
}
struct node {
int st,en;
} ed[maxnn];
int cnt;
int n,m;
void add(int a,int b) {
en[++tot]=b;
nex[tot]=las[a];
las[a]=tot;
}
void zadd(int a,int b) {
zen[++ztot]=b;
znex[ztot]=zlas[a];
zlas[a]=ztot;
}
stack<int > Q;
void tarjan(int v,int e) {
Q.push(v);
dfn[v]=low[v]=++vii;
for(int i=las[v]; i; i=nex[i]) {
if((e!=-1)&&((i^1)==e)) continue;
int u=en[i];
if(!dfn[u]) {
tarjan(u,i);
low[v]=min(low[u],low[v]);
} else {
low[v]=min(low[v],dfn[u]);
}
}
int r;
if(low[v]==dfn[v]) {
scc++;
do {
r=Q.top();
Q.pop();
belong[r]=scc;
} while(r!=v);
}
}
int goup(int x,int k) {
int s=log2(n);
for(int i=s; i>=0; i--) {
if((1<<i)&k) {
x=f[x][i];
}
}
return x;
}
int lca(int x,int y) {
if(dep[x]<dep[y]) swap(x,y);
x=goup(x,dep[x]-dep[y]);
if(x==y) return x;
int s=log2(n);
for(int i=s; i>=0; i--) {
if(f[x][i]!=f[y][i]) {
x=f[x][i];
y=f[y][i];
}
}
return f[x][0];
}
void dfs(int v,int fa) {
vis[v]=1;
dep[v]=dep[fa]+1;
f[v][0]=fa;
int s=log2(n);
for(int i=1; i<=s; i++) {
f[v][i]=f[f[v][i-1]][i-1];
}
for(int i=zlas[v]; i; i=znex[i]) {
int u=zen[i];
if(u!=fa) {
dfs(u,v);
}
}
}
void dfs2(int v,int fa) {
vis[v]=1;
for(int i=zlas[v]; i; i=znex[i]) {
int u=zen[i];
if(u!=fa) {
dfs2(u,v);
cnt1[v]+=cnt1[u];
cnt2[v]+=cnt2[u];
}
}
}
int main() {
//freopen("c.in","r",stdin);
//freopen("c.out","w",stdout);
int x,y;
n=R();
m=R();
for(int i=1; i<=m; i++) {
ed[++cnt].st=R();
ed[cnt].en=R();
add(ed[cnt].st,ed[cnt].en);
add(ed[cnt].en,ed[cnt].st);
}
for(int i=1; i<=n; i++) {
if(!dfn[i]) tarjan(i,-1);
}
for(int i=1; i<=n; i++) {
fff[i]=i;
}
for(int i=1; i<=n; i++) {
for(int j=las[i]; j; j=nex[j]) {
int u=en[j];
if(belong[u]==belong[i]) {
continue;
}
zadd(belong[i],belong[u]);
int fx=gf(belong[i]);
int fy=gf(belong[u]);
if(fx==fy) continue;
fff[fx]=fy;
}
}
for(int i=1; i<=n; i++)
if(!vis[belong[i]])
dfs(belong[i],belong[i]);
for(int i=1; i<=n; i++)
vis[i]=0;
int q;
q=R();
while(q--) {
x=R();
y=R();
x=belong[x];
y=belong[y];
if(gf(x)!=gf(y)) continue;
int d=lca(x,y);
cnt1[x]++;
cnt1[d]--;
cnt2[y]++;
cnt2[d]--;
}
for(int i=1; i<=n; i++)
if(!vis[belong[i]])
dfs2(belong[i],belong[i]);
for(int i=1; i<=cnt; i++) {
if(belong[ed[i].st]==belong[ed[i].en]) {
putchar('B');
continue;
}
if(f[belong[ed[i].st]][0]==belong[ed[i].en]) {
if(cnt1[belong[ed[i].st]]) {
putchar('R');
continue;
}
if(cnt2[belong[ed[i].st]]) {
putchar('L');
continue;
}
}
if(f[belong[ed[i].en]][0]==belong[ed[i].st]) {
if(cnt1[belong[ed[i].en]]) {
putchar('L');
continue;
}
if(cnt2[belong[ed[i].en]]) {
putchar('R');
continue;
}
}
putchar('B');
}
}