8
4
2016
0

[UOJ207] 共价大爷游长沙

虽然已经有官方题解了而且写的和我一样……但是我还来写一次题解凑文章数

首先看了一下题目,发现不会做,就去看题解。

题解中说:"用LCT统计子树异或和",我不会啊!

找到myy代码仔细看了一遍,大概也会统计子树异或和了。

首先我们考虑正常的LCT,你直接把两个child的和异或起来的和其实是你Access的那条链上的和。

那么统计子树就要从这里入手。

我们在Access时加上一些操作:如果原先选中的链不为Null,异或之;如果当前的选中的节点不为Null,异或之;

这样为什么就可以统计子树了呢?

(注意题目的性质,我们的子树异或和一定是Access访问过这个子树的全部节点,所以才能这么做)

考虑一开始啥都没有。

然后我们选中了一条链,那么原先的链啥也没有,我们在Pushup的时候就不考虑异或。

但是现在选中的链是存在的,我们异或一下。

那么我们就统计了这一条链。

之后同理

至于为什么要异或s_c,那是因为你在选中时统计了这个,之后Pushup时s_t又统计了一次

所以要还原

然后我们这题可以随机赋权值,每次碰到就异或一下,求解时确认这条边是否唯一存在即可。

代码跑得并不快(6097ms)

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

const int N=500005;

int n,m,ID,ans,h[N],en,fa[N],val[N],cnt;
pair<int,int> path[N];

inline void Read(int &x){
char ch;
while((ch=getchar())<'0' || ch>'9');
x=ch-'0';
while((ch=getchar())>='0' && ch<='9')x=x*10+ch-'0';
}

inline int Abs(const int &x){return x>0?x:-x;}

inline int Rand(){
return (rand()<<16)|rand();
}

struct Edge{
int b,next;
}e[N<<1];

inline void AddEdge(const int &sa,const int &sb){e[++en].b=sb;e[en].next=h[sa];h[sa]=en;}

struct Node{
int v,v_t,s_c,s_t;
bool rev;
Node *ch[2],*fa;
Node();
inline void Pushdown();
inline void Pushup();
}*tree[N],*Null;

Node::Node(){v=v_t=s_c=s_t=rev=0;ch[0]=ch[1]=fa=Null;}

inline void Node::Pushdown(){
if(rev){
    if(ch[0]!=Null)ch[0]->rev^=1;
    if(ch[1]!=Null)ch[1]->rev^=1;
    swap(ch[0]->ch[0],ch[0]->ch[1]);
    swap(ch[1]->ch[0],ch[1]->ch[1]);
	rev=0;
}
}

inline void Node::Pushup(){
s_t=v_t;s_c=v;
if(ch[0]!=Null)s_t^=ch[0]->s_t,s_c^=ch[0]->s_c;
if(ch[1]!=Null)s_t^=ch[1]->s_t,s_c^=ch[1]->s_c;
}

Node *GetNull(){Node *p=new Node();p->fa=p->ch[0]=p->ch[1]=p;return p;}
int Notroot(Node *x){return x->fa->ch[0]==x||x->fa->ch[1]==x;}
void Prepare(Node *x){if(Notroot(x))Prepare(x->fa);x->Pushdown();}

void Rotate(Node *x,int kind){
Node *y=x->fa,*z=y->fa;
y->ch[!kind]=x->ch[kind];
if(x->ch[kind]!=Null)x->ch[kind]->fa=y;
x->fa=z;
if(Notroot(y))z->ch[z->ch[1]==y]=x;
y->fa=x;
x->ch[kind]=y;
y->Pushup();
x->Pushup();
}

void Splay(Node *x){
Prepare(x);
while(Notroot(x)){
	Node *y=x->fa,*z=y->fa;
	if(!Notroot(y))Rotate(x,y->ch[0]==x);
    else {
        if(y->ch[0]==x && z->ch[0]==y){Rotate(y,1);Rotate(x,1);}
		else if(y->ch[0]==x && z->ch[1]==y){Rotate(x,1);Rotate(x,0);}
		else if(y->ch[1]==x && z->ch[0]==y){Rotate(x,0);Rotate(x,1);}
		else {Rotate(y,0);Rotate(x,0);}
    }
}
}

void Access(Node *x){
for(Node *y=Null;x!=Null;y=x,x=x->fa){
	Splay(x);
	if(x->ch[1]!=Null)x->v_t^=x->ch[1]->s_t^x->ch[1]->s_c;
	if(y!=Null)x->v_t^=y->s_t^y->s_c;
	x->ch[1]=y;
    x->Pushup();
}
}

inline void Makeroot(Node *x){
Access(x);
Splay(x);
x->rev^=1;
swap(x->ch[0],x->ch[1]);
}

inline void Link(Node *x,Node *y){
Makeroot(x);
Access(y);
Splay(y);
y->v_t^=x->s_t^x->s_c;
x->fa=y;
Access(x);
}

inline void Cut(Node *x,Node *y){
Makeroot(x);
Access(y);
Splay(y);
x->fa=Null;
y->ch[0]=Null;
x->Pushup();
}

inline void Change(Node *x,int y){Access(x);Splay(x);x->v^=y;x->Pushup();}
inline bool Query(Node *x,Node *y){Makeroot(x);Access(y);Splay(y);/*printf("DEBUG_Q: %d %d %d %d\n",y->v,y->v_t,y->v^y->v_t,ans);*/return (y->v^y->v_t)==ans;}
inline void dfs(int u){for(int i=h[u];i;i=e[i].next){int v=e[i].b;if(v==fa[u])continue;fa[v]=u;dfs(v);}}

int main(){
freopen("207.in","r",stdin);
freopen("207.out","w",stdout);
Read(ID);Read(n);Read(m);
if(ID==11){puts("OrzOrzOrz\nHello,world!\n233666");return 0;}
Null=GetNull();
for(int i=1;i<n;i++){
	int u,v;
    Read(u);Read(v);
	AddEdge(u,v);AddEdge(v,u);
}
dfs(1);
for(int i=1;i<=n;i++)tree[i]=new Node();
for(int i=2;i<=n;i++)tree[i]->fa=tree[fa[i]];
for(int i=0;i<m;i++){
	int opt,u,v,x,y;
    Read(opt);
    if(opt==1){Read(u);Read(v);Read(x);Read(y);Cut(tree[u],tree[v]);Link(tree[x],tree[y]);}
    if(opt==2){Read(x);Read(y);int tp=Rand();ans^=tp;Change(tree[x],tp);Change(tree[y],tp);path[++cnt]=make_pair(x,y);val[cnt]=tp;}
    if(opt==3){Read(x);Change(tree[path[x].first],val[x]);Change(tree[path[x].second],val[x]);ans^=val[x];}
    if(opt==4){Read(x);Read(y);puts(Query(tree[x],tree[y])?"YES":"NO");}
}
return 0;
}
Category: 其他OJ | Tags: OI uoj
8
1
2016
0

[BZOJ1303] [CQOI2009]中位数图

排序完了直接统计就好

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
 
const int N=100005;
 
int n,a[N],b,c[N],d[10*N],e[10*N],pos,ans;
 
void Read(int &x){
char ch;
while((ch=getchar())<'0' || ch>'9');
x=ch-'0';
while((ch=getchar())>='0' && ch<='9')x=x*10+ch-'0';
}
 
int main(){
freopen("1303.in","r",stdin);
freopen("1303.out","w",stdout);
Read(n);Read(b);
for(int i=1;i<=n;i++){Read(a[i]);if(a[i]==b)pos=i,a[i]=0;else a[i]=a[i]>b?1:-1;}
d[n]=1;e[n]=1;
for(int i=pos-1;i;i--){c[i]=c[i+1]+a[i];d[c[i]+n]++;}
for(int i=pos+1;i<=n;i++){c[i]=c[i-1]+a[i];e[c[i]+n]++;}
for(int i=0;i<=2*n-1;i++)ans+=d[i]*e[2*n-i];
printf("%d\n",ans);
return 0;
}
Category: BZOJ | Tags: OI bzoj
8
1
2016
0

[BZOJ4636] 蒟蒻的数列

因为我们只要最后知道答案就好了

所以我们离线

先排序,然后维护一个大根堆然后直接统计就好

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<algorithm>
using namespace std;
 
const int N=40005;
 
struct Node{
int a,b,k;
Node(){}
Node(int aa,int bb,int kk){a=aa;b=bb;k=kk;}
friend bool operator<(Node A,Node B){return A.a<B.a||(A.a==B.a && A.b<B.b);}
}a[N<<1];
 
class Heap{
private:
priority_queue<int> P,Q;
public:
inline void I(int x){P.push(x);}
inline void D(int x){Q.push(x);}
inline int T(){while(!Q.empty() && Q.top()==P.top())P.pop(),Q.pop();return P.empty()?0:P.top();}
}H;
 
int n,nn;
long long ans;
 
void Read(int &x){
char ch;
while((ch=getchar())<'0' || ch>'9');
x=ch-'0';
while((ch=getchar())>='0' && ch<='9')x=x*10+ch-'0';
}
 
int main(){
freopen("4636.in","r",stdin);
freopen("4636.out","w",stdout);
Read(n);
for(int i=1;i<=n;i++){
    int as,bs,ks;
    Read(as);Read(bs);Read(ks);
    a[++nn]=Node(as,0,ks);
    a[++nn]=Node(bs,1,ks);
}
a[++nn]=Node(0,0,0);
sort(a+1,a+nn+1);
int ft=0;
for(int i=1;i<=nn;i++){
    ans+=1ll*H.T()*(a[i].a-ft);
    ft=a[i].a;
    if(!a[i].b)H.I(a[i].k);
    else H.D(a[i].k);
}
printf("%lld\n",ans);
return 0;
}
Category: BZOJ | Tags: OI bzoj
8
1
2016
0

[BZOJ2618] [Cqoi2006]凸多边形

裸的半平面交

注意特判一下就好了

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;
 
const int N=50005;
const double eps=1e-17;
 
int n,Pn[15],cnt,first,last;
 
struct Point{
double x,y;
Point(){}
Point(double sa,double sb){x=sa;y=sb;}
friend Point operator+(Point A,Point B){return Point(A.x+B.x,A.y+B.y);}
friend Point operator-(Point A,Point B){return Point(A.x-B.x,A.y-B.y);}
friend Point operator*(Point A,double B){return Point(A.x*B,A.y*B);}
friend double operator*(Point A,Point B){return A.x*B.y-A.y*B.x;}
}poi[15][55],Px[N];
 
struct Line{
Point p,v;
double ang;
Line(){}
Line(Point A,Point B){p=A;v=B-A;ang=atan2(v.y,v.x);}
friend bool operator<(Line A,Line B){return A.ang<B.ang;}
}line[N],*Q[N];
 
double Dist2(Point A,Point B){return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y);}
Point GetPoint(Line A,Line B){return A.p+A.v*((B.v*(A.p-B.p))/(A.v*B.v));}
bool OnLeft(Point A,Line B){return (A-B.p)*B.v-eps<=0;}
 
void Intersection(){
first=last=0;
sort(line+1,line+cnt+1);
for(int i=1;i<=cnt;i++){
    while(last-first>=2 && !OnLeft(GetPoint(*Q[last],*Q[last-1]),line[i]))Q[last--]=NULL;
    if(last-first>=1 && fabs(Q[last]->v*line[i].v)<=eps)Q[last]=OnLeft(line[i].p,*Q[last])?line+i:Q[last];
    else Q[++last]=line+i;
}
while(last-first>=2 && !OnLeft(GetPoint(*Q[first+1],*Q[first+2]),*Q[last]))Q[++first]=NULL;
while(last-first>=2 && !OnLeft(GetPoint(*Q[last],*Q[last-1]),*Q[first+1]))Q[last--]=NULL;
}
 
double Area(){
//printf("%d %d\n",first,last);
if(last-first<=1)return 0.0;
Q[last+1]=Q[first+1];
cnt=0;
for(int i=first+1;i<=last;i++){
    Px[++cnt]=GetPoint(*Q[i],*Q[i+1]);
    //printf("%.2lf %.2lf\n",Px[cnt].x,Px[cnt].y);
}
Px[cnt+1]=Px[1];
double Ans=0.0;
for(int i=1;i<=cnt;i++){
    Ans+=Px[i]*Px[i+1];
}
return Ans/2.0;
}
 
int main(){
freopen("2618.in","r",stdin);
freopen("2618.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++){
    scanf("%d",&Pn[i]);
    for(int j=1;j<=Pn[i];j++)scanf("%lf %lf",&poi[i][j].x,&poi[i][j].y);
    poi[i][Pn[i]+1]=poi[i][1];
    for(int j=1;j<=Pn[i];j++)line[++cnt]=Line(poi[i][j],poi[i][j+1]);
}
Intersection();
printf("%.3lf\n",Area());
return 0;
}
Category: BZOJ | Tags: OI bzoj
8
1
2016
0

[BZOJ2458] [BeiJing2011]最小三角形

考虑分治

首先我们按照x轴排序,然后我们要求每段处理时y轴有序

然后排除一些不可能的情况后暴力统计就好了

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
 
const int N=200005;
 
int n;
double ans=1e10;
 
struct Point{
int x,y;
friend bool operator<(Point A,Point B){return A.y<B.y;}
}poi[N],_point[N];
 
bool cmp(Point A,Point B){return A.x<B.x;}
double Abs(int x){return x>0?(double)x:(double)-x;}
double Di(Point A,Point B){return sqrt((double)(A.x-B.x)*(A.x-B.x)+(double)(A.y-B.y)*(A.y-B.y));}
 
void Solve(int l,int r){
if(l==r)return;
if(l+1==r){if(poi[r]<poi[l])swap(poi[l],poi[r]);return;}
int mid=l+r>>1,tp=poi[mid].x;
Solve(l,mid);Solve(mid+1,r);
int l1=l,l2=mid+1;
for(int i=l;i<=r;i++){
    if(l2>r||(l1<=mid && poi[l1]<poi[l2]))_point[i]=poi[l1++];
    else _point[i]=poi[l2++];
}
memcpy(poi+l,_point+l,sizeof(Point)*(r-l+1));
for(int i=l,tail=l;i<=r;i++){
    if(Abs(poi[i].x-tp)<ans/2.0){
        while(poi[i].y-poi[tail].y>ans/2.0)tail++;
        for(int j=tail;j<i-1;j++)if(Abs(poi[j].x-tp)<ans/2.0)if(poi[i].y-poi[j].y<ans/2.0)for(int k=j+1;k<i;k++)ans=min(ans,Di(poi[i],poi[j])+Di(poi[i],poi[k])+Di(poi[j],poi[k]));
    }
}
}
 
int main(){
freopen("2458.in","r",stdin);
freopen("2458.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d %d",&poi[i].x,&poi[i].y);
sort(poi+1,poi+n+1,cmp);
Solve(1,n);
printf("%lf\n",ans);
return 0;
}
Category: BZOJ | Tags: OI bzoj
8
1
2016
0

[BZOJ3767] A+B Problem加强版

Python大法好

a,b=map(int,raw_input().split())
print(a+b)
Category: BZOJ | Tags: OI bzoj
8
1
2016
0

[BZOJ2037] [Sdoi2008]Sue的小球

考虑dp之后造成的影响

我们思考对于整体的影响,因为是区间dp我们分别统计就好了

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

const int N=1005;

int n,x0,dp[N][N][2],sum[N];

struct Thing{
int x,y,v;
friend inline bool operator<(const Thing &A,const Thing &B){return A.x<B.x || (A.x==B.x && A.y<B.y);}
}a[N];

int Abs(int x){return x>0?x:-x;}

int main(){
freopen("2037.in","r",stdin);
freopen("2037.out","w",stdout);
scanf("%d %d",&n,&x0);
for(int i=1;i<=n;i++)scanf("%d",&a[i].x);
for(int i=1;i<=n;i++)scanf("%d",&a[i].y);
for(int i=1;i<=n;i++)scanf("%d",&a[i].v);
sort(a+1,a+n+1);
for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i].v;
for(int i=1;i<=n;i++)dp[i][i][0]=dp[i][i][1]=a[i].y-Abs(a[i].x-x0)*sum[n];
for(int len=1;len<n;len++){
    for(int i=1;i<=n-len;i++){
		dp[i][i+len][0]=max(dp[i+1][i+len][1]+a[i].y-(sum[n]-sum[i+len]+sum[i])*Abs(a[i].x-a[i+len].x),dp[i+1][i+len][0]+a[i].y-(sum[n]-sum[i+len]+sum[i])*Abs(a[i].x-a[i+1].x));
		dp[i][i+len][1]=max(dp[i][i+len-1][1]+a[i+len].y-(sum[n]-sum[i+len-1]+sum[i-1])*Abs(a[i+len-1].x-a[i+len].x),dp[i][i+len-1][0]+a[i+len].y-(sum[n]-sum[i+len-1]+sum[i-1])*Abs(a[i].x-a[i+len].x));
    }
}
printf("%.3lf\n",(double)(max(dp[1][n][0],dp[1][n][1])/1000.0));
return 0;
}
Category: BZOJ | Tags: OI bzoj
8
1
2016
0

[BZOJ2901] 矩阵求和

一开始以为是一个高明的数据结构,后来发现直接拆式子就行了

举个$2*2$矩阵的例子

第一个矩阵

$$

 \begin{bmatrix}

 a_1 & a_2 \\

 a_3 & a_4 \\

 \end{bmatrix}

$$

第二个矩阵

$$

 \begin{bmatrix}

 b_1 & b_2 \\

 b_3 & b_4 \\

 \end{bmatrix}

$$

那么我们来乘一下,结果是

$$

 \begin{bmatrix}

 a_1*b_1+a_2*b_3 & a_2*b_4+a_1*b_2 \\

 a_3*b_1+a_4*b_3 & a_4*b_4+a_3*b_2 \\

 \end{bmatrix}

$$

加一下得到$a_1*(b_1+b_2)+a_2*(b_3+b_4)+a_3*(b_1+b_2)+a_4*(b_3+b_4)$

组合一下得到$(a_1+a_3)*(b_1+b_2)+(a_2+a_4)*(b_3*b_4)$

也就是第一个矩阵记录向上的前缀和,第二个矩阵记录向左的前缀和

然后乘一下就好了

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

const register int N=2005;

static int n,m,a[N][N],b[N][N];

inline void Read(register int &x){
register char ch;
while((ch=getchar())<'0' || ch>'9');
x=ch-'0';
while((ch=getchar())>='0' && ch<='9')x=x*10+ch-'0';
}

int main(){
freopen("2901.in","r",stdin);
freopen("2901.out","w",stdout);
Read(n);Read(m);
for(register int i=1;i<=n;i++)for(register int j=1;j<=n;j++)Read(a[i][j]),a[i][j]+=a[i-1][j];
for(register int i=1;i<=n;i++)for(register int j=1;j<=n;j++)Read(b[i][j]),b[i][j]+=b[i][j-1];
while(m--){
	register int A,B,C,D;
	Read(A);Read(B);Read(C);Read(D);
	if(A>C)A^=C^=A^=C;
	if(B>D)B^=D^=B^=D;
	register long long ans=0;
    for(register int i=1;i<=n;i++)ans+=(1ll*a[C][i]-a[A-1][i])*(1ll*b[i][D]-b[i][B-1]);
    printf("%lld\n",ans);
}
return 0;
}
Category: BZOJ | Tags: OI bzoj
8
1
2016
0

[BZOJ4063] [Cerc2012]Darts

模拟即可

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

int Dist2(int x,int y){
return x*x+y*y;
}

int test,n;

int main(){
freopen("4063.in","r",stdin);
freopen("4063.out","w",stdout);
scanf("%d",&test);
while(test--){
	long long ans=0;
	scanf("%d",&n);
    for(int i=1;i<=n;i++){
		int x,y;
        scanf("%d %d",&x,&y);
        int t=Dist2(x,y);
		if(t<=20*20){ans+=10;}
		else if(t<=40*40){ans+=9;}
		else if(t<=60*60){ans+=8;}
		else if(t<=80*80){ans+=7;}
		else if(t<=100*100){ans+=6;}
		else if(t<=120*120){ans+=5;}
		else if(t<=140*140){ans+=4;}
		else if(t<=160*160){ans+=3;}
        else if(t<=180*180){ans+=2;}
        else if(t<=200*200){ans+=1;}
    }
    printf("%lld\n",ans);
}
return 0;
}
Category: BZOJ | Tags: OI bzoj
8
1
2016
0

[BZOJ2241] [SDOI2011]打地鼠

模拟一下即可

注意适当的常数优化

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

const int N=105,INF=2100000000;

int mp[N][N],mp2[N][N],n,m,ans=INF;

int Test(int r,int c){
int cnt=0;
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)mp2[i][j]=mp[i][j];
for(int i=1;i+r-1<=n;i++){
	for(int j=1;j+c-1<=m;j++){
        if(mp2[i][j]){
			int tp=mp2[i][j];
			cnt+=tp;
            for(int k=1;k<=r;k++){
				for(int l=1;l<=c;l++){
                    mp2[i+k-1][j+l-1]-=tp;
                    if(mp2[i+k-1][j+l-1]<0)return INF;
				}
            }
        }
	}
}
for(int i=1;i<=n;i++){
	for(int j=1;j<=m;j++){
		if(mp2[i][j])return INF;
	}
}
return cnt;
}

int main(){
freopen("2241.in","r",stdin);
freopen("2241.out","w",stdout);
scanf("%d %d",&n,&m);
int tx=0;
for(int i=1;i<=n;i++){
	for(int j=1;j<=m;j++){
		scanf("%d",&mp[i][j]);tx+=mp[i][j];
	}
}
for(int r=1;r<=n;r++){
    for(int c=1;c<=m;c++){
		if(tx%(r*c) || tx/(r*c)+1>ans)continue;
        ans=min(ans,Test(r,c));
    }
}
printf("%d\n",ans);
return 0;
}
Category: BZOJ | Tags: OI bzoj

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com