A.小w、小j和小z
我可能是个傻子,两个人i,j相撞的要求就是
si<sj,ti>tj或者si>sj,ti<tj
s
i
<
s
j
,
t
i
>
t
j
或
者
s
i
>
s
j
,
t
i
<
t
j
,然后我都想到按s排序了!结果我去dp逆序对了囧结果
O(logwnk)
O
(
l
o
g
w
n
k
)
水了80,其实按s排序之后不就是问你最少删掉几个使得剩下的序列为上升序列嘛…直接求个lis就好了
复杂度
O(logwnlogn)
O
(
l
o
g
w
n
l
o
g
n
)
B.小h的树
首先考虑K=n的点,我们发现答案就是所有边长*2-树的直径
可以发现我们选的K个点一定是连通子树,因此所求答案其实就是这K个点的虚树边长和*2-虚树直径。
我们可以dp,f[x][j][0/1/2]表示x子树连通块有k个点,内有0/1/2个直径端点的最小答案,分情况讨论一下即可,精细转移。
复杂度
O(n2)
O
(
n
2
)
考试时真的是zz,一直觉得这条路径的贡献没法一起算进dp数组里…所以只写了20暴力滚粗
C.小x的城池
考试时写了10分暴力+35分没有reverse的。
我们用线段树维护,每个区间记答案,还没成为答案的A城市的人口情况,B人口的最大值,每次合并时考虑右儿子对左儿子的影响即可。
考虑有reverse操作怎么办,我们多维护一些左右起的东西,中间的不影响的边我们就不管了。
每个节点记
//ans 区间内的答案 ar[i],区间内能走到右端点的人口为i的A城市个数
//al[i],区间内能走到左端点的人口为i的A城市个数
//id 既能走到左端点又能走到右端点的A城市的人口(最多一个)
//mxl 左起最大B值 mxr 右起最大B值 alll 全都向左 allr全都向右
这些东西来转移,合并时看mid->mid+1这条边的方向来看是右儿子影响左儿子,还是左儿子影响右儿子。每条边的情况可以用一个BIT来维护。另外我们还要维护每一个区间取反后的信息,这样就可以实现对一段区间的快速翻转。
复杂度 O((n+q)logn75) O ( ( n + q ) l o g n 75 )
另外这题卡空间233
我们可以考虑对于叶子结点都不开data,每次用到时初始化一个出来即可,这样就省掉了一半的空间开销。(orz pickuowin最初提出的这个想法)
A
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
#define eps 1e-5
inline char gc(){
static char buf[1<<16],*S,*T;
if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=gc();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
return x*f;
}
int n,K;
double c[N],a[N];
struct Icefox{
int x,v;
friend bool operator<(Icefox a,Icefox b){return a.x==b.x?a.v>b.v:a.x<b.x;}
}b[N];
inline bool jud(double mid){
for(int i=1;i<=n;++i) a[i]=mid*b[i].v+b[i].x;
int res=1;c[1]=a[1];
for(int i=2;i<=n;++i){
if(a[i]>c[res]) c[++res]=a[i];
else c[lower_bound(c+1,c+res+1,a[i])-c]=a[i];
}return n-res<=K;
}
int main(){
// freopen("a.in","r",stdin);
n=read();K=read();
for(int i=1;i<=n;++i) b[i].x=read(),b[i].v=read();
sort(b+1,b+n+1);
double l=0,r=2e9;
while(r-l>=eps){
double mid=(l+r)/2;
if(jud(mid)) l=mid;
else r=mid;
}if(abs(l-2e9)<=eps) puts("Forever");
else printf("%.4lf\n",l);
return 0;
}
B
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 3010
inline char gc(){
static char buf[1<<16],*S,*T;
if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=gc();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
return x*f;
}
int n,K,h[N],num=0;
struct edge{
int to,next,val;
}data[N<<1];
namespace sol1{
int ans=inf,a[N],fa[N],dep[N],w[N],dis[20][20];bool ban[N];
inline void dfs(int lev,int res){
if(res>ans) return;
if(lev>K){ans=res;return;}
for(int i=1;i<=n;++i){
if(ban[i]) continue;ban[i]=1;a[lev]=i;
dfs(lev+1,res+dis[i][a[lev-1]]);ban[i]=0;
}
}inline void dfs1(int x){
for(int i=h[x];i;i=data[i].next){
int y=data[i].to;if(y==fa[x]) continue;
fa[y]=x;dep[y]=dep[x]+1;w[y]=data[i].val;dfs1(y);
}
}inline int calc(int x,int y){
int res=0;
while(x!=y){
if(dep[x]<dep[y]) swap(x,y);
res+=w[x];x=fa[x];
}return res;
}
inline void gao(){
dfs1(1);
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
dis[i][j]=calc(i,j);
dfs(1,0);
printf("%d\n",ans);
}
}
namespace sol2{
int ans=0,dis[N],mx;
inline void dfs(int x,int Fa){
if(dis[x]>dis[mx]) mx=x;
for(int i=h[x];i;i=data[i].next){
int y=data[i].to;if(y==Fa) continue;
dis[y]=dis[x]+data[i].val;dfs(y,x);
}
}
inline void gao(){
for(int i=1;i<=num;i++) ans+=data[i].val;
mx=0;dfs(1,0);int x=mx;mx=0;dis[x]=0;dfs(x,0);
ans-=dis[mx];printf("%d\n",ans);
}
}
namespace sol3{
int ans=inf,f[N][N][3],sz[N];//f[x][j][0/1/2] x子树连通块有k个点,内有0/1/2个直径端点的最小答案
inline void Min(int &x,int y){if(y<x) x=y;}
inline void dfs(int x,int Fa){
sz[x]=1;memset(f[x],inf,sizeof(f[x]));f[x][1][0]=f[x][1][1]=f[x][1][2]=0;
for(int i=h[x];i;i=data[i].next){
int y=data[i].to;if(y==Fa) continue;
dfs(y,x);int val=data[i].val;
for(int i=sz[x];i>=1;--i)
for(int j=1;j<=sz[y];++j){
if(i+j>K) break;
Min(f[x][i+j][0],f[x][i][0]+f[y][j][0]+2*val);
Min(f[x][i+j][1],f[x][i][1]+f[y][j][0]+2*val);
Min(f[x][i+j][1],f[x][i][0]+f[y][j][1]+val);
Min(f[x][i+j][2],f[x][i][0]+f[y][j][2]+2*val);
Min(f[x][i+j][2],f[x][i][1]+f[y][j][1]+val);
Min(f[x][i+j][2],f[x][i][2]+f[y][j][0]+2*val);
}sz[x]+=sz[y];
}Min(ans,f[x][K][0]);Min(ans,f[x][K][1]);Min(ans,f[x][K][2]);
}inline void gao(){
dfs(1,0);
printf("%d\n",ans);
}
}
int main(){
// freopen("a.in","r",stdin);
n=read();K=read();
for(int i=1;i<n;++i){
int x=read(),y=read(),val=read();
data[++num].to=y;data[num].next=h[x];h[x]=num;data[num].val=val;
data[++num].to=x;data[num].next=h[y];h[y]=num;data[num].val=val;
}if(n<=10){sol1::gao();}
else if(n==K){sol2::gao();}
else sol3::gao();
return 0;
}
C
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
int n,Q,a[N];bool op[N];
char s[10];
namespace sol1{
bool c[N],ban[N];//c[i]=1 i->i+1 c[i]=0 i<-i+1
inline int calc(){
int l=1,res=0,mx2=0;
for(int i=1;i<=n;++i) ban[i]=0;
for(int i=1;i<=n;++i){
if(c[i]){
if(!l) l=i;continue;
}if(l){
int mx=0;
for(int j=i;j>=l;--j){
if(!op[j]) mx=max(mx,a[j]);
else ban[j]|=mx>a[j];
}l=0;if(op[i]) mx2=0;else mx2=a[i];
}if(!op[i+1]) mx2=max(mx2,a[i+1]);
else ban[i+1]|=mx2>a[i+1];
}for(int i=1;i<=n;++i) res+=ban[i];return res;
}
inline void gao(){
for(int i=1;i<n;++i) c[i]=1;c[n]=0;
while(Q--){
scanf("%s",s+1);int x=read(),y=read();
if(s[1]=='R'){
for(int i=x;i<y;++i) c[i]^=1;
}else a[x]=y;printf("%d\n",calc());
}
}
}
namespace sol2{
struct node{
int ans,a[76],mx;
}tr[N<<2];
inline void pushup(int p){
tr[p].ans=tr[p<<1].ans+tr[p<<1|1].ans;
tr[p].mx=max(tr[p<<1].mx,tr[p<<1|1].mx);
for(int i=0;i<=75;++i) tr[p].a[i]=tr[p<<1].a[i]+tr[p<<1|1].a[i];
for(int i=tr[p<<1|1].mx-1;i>=0;--i)
tr[p].ans+=tr[p<<1].a[i],tr[p].a[i]-=tr[p<<1].a[i];
}inline void build(int p,int l,int r){
if(l==r){if(op[l]) tr[p].a[a[l]]++;else tr[p].mx=a[l];return;}
int mid=l+r>>1;build(p<<1,l,mid);build(p<<1|1,mid+1,r);pushup(p);
}inline void change(int p,int l,int r,int x,int y){
if(l==r){if(op[l]) tr[p].a[a[l]]--,tr[p].a[y]++;else tr[p].mx=y;a[x]=y;return;}
int mid=l+r>>1;
if(x<=mid) change(p<<1,l,mid,x,y);
else change(p<<1|1,mid+1,r,x,y);pushup(p);
}inline void gao(){
build(1,1,n);
while(Q--){
scanf("%s",s+1);int x=read(),y=read();
change(1,1,n,x,y);printf("%d\n",tr[1].ans);
}
}
}
namespace sol3{
int rt=0,owo=0,ofo=0;
bool c[N];
struct Icefox{
int ans,ar[76],al[76],mxl,mxr,id;bool alll,allr;
//ans 区间内的答案 ar[i],区间内能走到右端点的人口为i的A城市个数
//al[i],区间内能走到左端点的人口为i的A城市个数
//id 既能走到左端点又能走到右端点的A城市的人口(最多一个)
//mxl 左起最大B值 mxr 右起最大B值 alll 全都向左 allr全都向右
friend Icefox operator+(Icefox a,Icefox b){// ->
Icefox res;res.ans=a.ans+b.ans;
res.alll=0;res.allr=a.allr&b.allr;
res.mxl=max(a.mxl,a.allr?b.mxl:0);
res.mxr=b.mxr;int lim=b.mxl;res.id=-1;
for(int i=0;i<=75;++i){
res.al[i]=a.al[i];res.ar[i]=b.ar[i];
if(b.id==i) res.ar[i]++;
if(i<lim){
res.ans+=a.ar[i]+(a.id==i);continue;
}if(a.id==i){
if(!b.allr) res.al[i]++;
else res.id=i;
}if(b.allr) res.ar[i]+=a.ar[i];
}return res;
}friend Icefox operator-(Icefox a,Icefox b){// <-
Icefox res;res.ans=a.ans+b.ans;
res.allr=0;res.alll=a.alll&b.alll;
res.mxr=max(b.mxr,b.alll?a.mxr:0);
res.mxl=a.mxl;int lim=a.mxr;res.id=-1;
for(int i=0;i<=75;++i){
res.ar[i]=b.ar[i];res.al[i]=a.al[i];
if(a.id==i) res.al[i]++;
if(i<lim){
res.ans+=b.al[i]+(b.id==i);continue;
}if(b.id==i){
if(!a.alll) res.ar[i]++;
else res.id=i;
}if(a.alll) res.al[i]+=b.al[i];
}return res;
}
}seq[N],rev[N];
struct node{
int ls,rs,id;bool tag;
}tr[N<<1];
inline void add(int x){//0-- i->i+1 1-- i<-i+1
for(;x<n;x+=x&-x) c[x]^=1;
}inline bool ask(int x){
int res=0;for(;x;x-=x&-x) res^=c[x];return res;
}inline Icefox unit(int x){
Icefox res;
if(op[x]){
res.alll=res.allr=1;res.mxl=res.mxr=0;res.id=a[x];res.ans=0;
memset(res.al,0,sizeof(res.al));memset(res.ar,0,sizeof(res.ar));
}else{
res.alll=res.allr=1;res.mxl=res.mxr=a[x];res.id=-1;res.ans=0;
memset(res.al,0,sizeof(res.al));memset(res.ar,0,sizeof(res.ar));
}return res;
}
inline void pushup(int p,int mid){
int l=tr[p].ls,r=tr[p].rs;
if(ask(mid)){
seq[tr[p].id]=(tr[l].id?seq[tr[l].id]:unit(mid))-(tr[r].id?seq[tr[r].id]:unit(mid+1));
rev[tr[p].id]=(tr[l].id?rev[tr[l].id]:unit(mid))+(tr[r].id?rev[tr[r].id]:unit(mid+1));
}else{
seq[tr[p].id]=(tr[l].id?seq[tr[l].id]:unit(mid))+(tr[r].id?seq[tr[r].id]:unit(mid+1));
rev[tr[p].id]=(tr[l].id?rev[tr[l].id]:unit(mid))-(tr[r].id?rev[tr[r].id]:unit(mid+1));
}
}inline void dorev(int p){
if(!tr[p].id) return;tr[p].tag^=1;
swap(seq[tr[p].id],rev[tr[p].id]);
}inline void pushdown(int p){
if(!tr[p].tag) return;tr[p].tag=0;
dorev(tr[p].ls);dorev(tr[p].rs);
}inline void build(int &p,int l,int r){
p=++owo;if(l==r) return;tr[p].id=++ofo;
int mid=l+r>>1;build(tr[p].ls,l,mid);
build(tr[p].rs,mid+1,r);pushup(p,mid);
}inline void change(int p,int l,int r,int x){
if(l==r) return;int mid=l+r>>1;pushdown(p);
if(x<=mid) change(tr[p].ls,l,mid,x);
else change(tr[p].rs,mid+1,r,x);pushup(p,mid);
}inline void reverse(int p,int l,int r,int x,int y){
if(x<=l&&r<=y){dorev(p);return;}
int mid=l+r>>1;pushdown(p);
if(x<=mid) reverse(tr[p].ls,l,mid,x,y);
if(y>mid) reverse(tr[p].rs,mid+1,r,x,y);pushup(p,mid);
}inline void gao(){
build(rt,1,n);
while(Q--){
scanf("%s",s+1);int x=read(),y=read();
if(s[1]=='U') a[x]=y,change(rt,1,n,x);
else add(y),add(x),reverse(rt,1,n,x,y);
printf("%d\n",seq[tr[rt].id].ans);
}
}
}
int main(){
// freopen("a2.in","r",stdin);
// freopen("a.ans","w",stdout);
n=read();Q=read();
for(int i=1;i<=n;++i){
a[i]=read();scanf("%s",s+1);op[i]=s[1]=='A';
}if((ll)n*Q<=1e8) sol1::gao();
else sol3::gao();
return 0;
}