2020 CCPC Wannafly Winter Camp Day5 Div.1&2

大失败。

  • A 签到题,题面太长没做。
  • B 树上传递闭包问题。原本是想着倒着做能求解答案,使用并查集,后来发现并查集并不对 正解是维护一个可到达点的数量利用树的特点容斥了一下。
code
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cctype>
#include<queue>
#include<deque>
#include<stack>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1000000000000000000ll
#define inf 1000000001
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define gi(x) scanf("%lf",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define rep(p,n,i) for(int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define pii pair<int,int>
#define mk make_pair
#define P 1000000007ll
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define EPS 1e-10
#define sq sqrt
#define S second
#define F first
#define mod 998244353
#define r(x) c[x].r
#define l(x) c[x].l
#define cc(x) c[x].cc
#define mx2(x) t[x].mx2
#define max(x,y) ((x)<(y)?y:x)
using namespace std;
char *fs,*ft,buf[1<<15];
inline char gc()
{
    return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
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;
}
const int MAXN=500010;
int n,m;
int a[MAXN],b[MAXN];
int f[MAXN],c[MAXN],w[MAXN];
int main()
{
	//freopen("1.in","r",stdin);
	n=read();m=read();
	rep(1,n-1,i)
	{
		f[i]=1;
		a[i]=read(),b[i]=read();
	}
	f[n]=1;
	rep(1,m,j)w[j]=read();
	for(int i=m;i>=1;--i)
	{
		int x=a[w[i]],y=b[w[i]];
		f[x]=f[y]=f[x]+f[y]-c[w[i]];
		c[w[i]]=f[x];
	}
	rep(1,n,i)printf("%d ",f[i]);
	return 0;
}
  • C 一个简单的区间dp 利用归纳法来求不同区间的代价,不同区间我使用树状数组来数点。
code
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cctype>
#include<queue>
#include<deque>
#include<stack>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1000000000000000000ll
#define inf 1000000001
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define gi(x) scanf("%lf",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define rep(p,n,i) for(int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define pii pair<int,int>
#define mk make_pair
#define P 1000000007ll
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define EPS 1e-10
#define sq sqrt
#define S second
#define F first
#define mod 998244353
#define v(x) t[x].v
#define r(x) t[x].r
#define l(x) t[x].l
#define mx2(x) t[x].mx2
#define max(x,y) ((x)<(y)?y:x)
using namespace std;
char *fs,*ft,buf[1<<15];
inline char gc()
{
    return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
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;
}
const int MAXN=510,N=200010;
int n,m;
int f[MAXN][MAXN];//f[i][j]表示i~j这个区间所形成的线段树的最小值。
//f[i][j]=min{f[i][k]+f[k+1][j]+cost[i][j]};
int cost[MAXN][MAXN];
struct wy
{
	int l,r;
}t[N],h[N];
inline int cmp(wy a,wy b){return a.l<b.l;}
inline int cmp1(wy a,wy b){return a.r<b.r;}
int c[MAXN],v[MAXN],s[MAXN],b[MAXN][MAXN];
inline void add(int x,int y)
{
	while(x<=n)
	{
		c[x]+=y;
		x+=x&(-x);
	}
}
inline int ask(int x)
{
	int cnt=0;
	while(x)
	{
		cnt+=c[x];
		x-=x&(-x);
	}
	return cnt;
}
inline void add1(int x,int y)
{
	while(x<=n)
	{
		s[x]+=y;
		x+=x&(-x);
	}
}
inline int ask1(int x)
{
	int cnt=0;
	while(x)
	{
		cnt+=s[x];
		x-=x&(-x);
	}
	return cnt;
}
int main()
{
	//freopen("1.in","r",stdin);
	n=read();m=read();
	rep(1,m,i){l(i)=read();r(i)=read();add(r(i),1),++b[l(i)][r(i)];h[i]=t[i];}
	sort(t+1,t+1+m,cmp);
	sort(h+1,h+1+m,cmp1);
	//rep(1,m,i)cout<<t[i].l<<' '<<t[i].r<<endl;
	int w=m;
	for(int i=n;i>=1;--i)
	{
		v[i]=m-w;
		while(l(w)==i)--w;
	}
	w=0;int wc=1,ws=0;
	rep(1,n,i)
	{
		while(l(ws+1)==i)add1(r(ws+1),1),++ws;
		rep(i,n,j)
		{
			int ww=w+v[j];//无用
			int w1=ask(j)-b[i][j];//包含
			int w3=ws-ask1(j-1);//被包含
			int w2=m-ww-w1-w3;//相交
			cost[i][j]=w2+w1;
			if(i==j)cost[i][j]+=w3;
			else cost[i][j]-=w3;
			f[i][j]=inf;
		}
		while(h[w+1].r==i)++w;
		while(l(wc)==i)add(r(wc),-1),++wc;
		f[i][i]=cost[i][i];
	}
	/*rep(1,n,i)
	{
		rep(i,n,j)
		cout<<i<<' '<<j<<' '<<cost[i][j]<<endl;
		cout<<endl;
	}*/
	rep(2,n,len)
	{
		for(int i=1;i<=n-len+1;++i)
		{
			int j=i+len-1;
			rep(i,j-1,k)
			{
				f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+cost[i][j]);
			}
		}
	}
	printf("%d\n",f[1][n]);
	return 0;
}
  • D 一个求解多个圆相交部分的计算几何,没太看懂相交的面积怎么算 咕咕。

题目

题解代码

  • E 一个简单的枚举问题。
code
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cctype>
#include<queue>
#include<deque>
#include<stack>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1000000000000000000ll
#define inf 1000000001
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define gi(x) scanf("%lf",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define rep(p,n,i) for(int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define pii pair<int,int>
#define mk make_pair
#define P 1000000007ll
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define EPS 1e-10
#define sq sqrt
#define S second
#define F first
#define mod 998244353
#define r(x) c[x].r
#define l(x) c[x].l
#define cc(x) c[x].cc
#define mx2(x) t[x].mx2
#define max(x,y) ((x)<(y)?y:x)
using namespace std;
char *fs,*ft,buf[1<<15];
inline char gc()
{
    return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
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;
}
const int MAXN=310;
int n;
int a[MAXN],b[MAXN];
int c[MAXN][MAXN];
int main()
{
	//freopen("1.in","r",stdin);
	n=read();
	rep(1,n,i)a[i]=read();
	rep(1,4,i)b[i]=read();
	for(int i=n;i>=1;--i)
	{
		rep(1,n,j)c[i][j]=c[i+1][j];
		++c[i][a[i]];
	}
	ll ans=0;
	rep(1,n,i)
	{
		rep(i+1,n,j)
		{
			if(b[1]==b[2]&&a[i]!=a[j])continue;
			if(a[i]==a[j]&&b[1]!=b[2])continue;
			rep(j+1,n,k)
			{
				if(b[1]==b[3]&&a[i]!=a[k])continue;
				if(b[1]!=b[3]&&a[i]==a[k])continue;
				if(b[2]==b[3]&&a[j]!=a[k])continue;
				if(b[2]!=b[3]&&a[j]==a[k])continue;
				if(b[1]==b[4]){ans+=c[k+1][a[i]];continue;}
				if(b[2]==b[4]){ans+=c[k+1][a[j]];continue;}
				if(b[3]==b[4]){ans+=c[k+1][a[k]];continue;}
				int ww=c[k+1][a[i]];
				if(b[1]!=b[2])ww+=c[k+1][a[j]];
				if(b[1]!=b[3]&&b[2]!=b[3])ww+=c[k+1][a[k]];
				ans+=n-k-ww;
			}
		}
	}
	printf("%lld\n",ans);
	return 0;
}
  • F dp多项式题目,简单版的都不会求,更别提需要插值版的了。
    题目
    题解
  • G 一个逆元相关的无聊题目,复杂度无法证明。
code
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cctype>
#include<queue>
#include<deque>
#include<stack>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1000000000000000000ll
#define inf 1000000001
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define gi(x) scanf("%lf",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define rep(p,n,i) for(int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define pii pair<int,int>
#define mk make_pair
#define P 1000000007ll
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define EPS 1e-10
#define sq sqrt
#define S second
#define F first
#define mod 998244353
#define r(x) c[x].r
#define l(x) c[x].l
#define cc(x) c[x].cc
#define mx2(x) t[x].mx2
#define max(x,y) ((x)<(y)?y:x)
using namespace std;
char *fs,*ft,buf[1<<15];
inline char gc()
{
    return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
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;
}
const int MAXN=1000010;
int T;
int p,B,top,top1;
int inv[MAXN];
struct wy
{
	int x,y;
}s[MAXN],w[MAXN];
inline int cmp(wy a,wy b){return a.x<b.x;}
int main()
{
    //freopen("1.in","r",stdin);
	//freopen("1.out","w",stdout);

	T=read();
	while(T--)
	{
		p=read();top1=top=0;
		if(p==2){printf("0\n");continue;}
		if(p==3){printf("1\n");printf("2 2\n");continue;}
		
		B=(int)sqrt(p*1.0);
		int i=3;inv[1]=1;
		inv[2]=p-(ll)inv[p%2]*(p/2)%p;
		s[top=1].x=2;s[top].y=inv[2];
		w[++top1].x=inv[2];w[top1].y=2;
		while(i<p)
		{
			inv[i]=p-(ll)inv[p%i]*(p/i)%p;
			if(inv[i]<=s[top].y)
			{
				if(i==inv[i]){s[++top].x=i,s[top].y=inv[i];break;}
				if(i==s[top].y)break;
				s[++top].x=i,s[top].y=inv[i];
				w[++top1].x=inv[i];w[top1].y=i;
			}
			++i;
		}
		printf("%d\n",top+top1);
		rep(1,top,i)printf("%d %d\n",s[i].x,s[i].y);
        for(int i=top1;i>=1;--i)printf("%d %d\n",w[i].x,w[i].y);
	}
    return 0;
}
  • H 平面找点问题。不懂不会。
    题目
    题解
  • I 求一个矩阵的最大值。直接树套树,稍微有点卡空间。
code
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cctype>
#include<queue>
#include<deque>
#include<stack>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1000000000000000000ll
#define inf 100000000000000000ll
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define gi(x) scanf("%lf",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define rep(p,n,i) for(int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define pii pair<int,int>
#define mk make_pair
#define P 1000000007ll
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define EPS 1e-10
#define sq sqrt
#define S second
#define F first
#define mod 998244353
#define r(x) c[x].r
#define l(x) c[x].l
#define cc(x) c[x].cc
#define mx2(x) t[x].mx2
#define max(x,y) ((x)<(y)?y:x)
using namespace std;
char *fs,*ft,buf[1<<15];
inline char gc()
{
    return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
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;
}
const int MAXN=2010;
ll a[MAXN][MAXN],ans;
int n,m1,m2,cnt,root,xx,yy,cx,cy;
struct V{ll t[MAXN<<2];int l,r;}c[MAXN<<1];
inline void build1(int x,int rt,int L,int R,int pos)
{
	if(L==R){c[x].t[rt]=a[pos][L];return;}
	int mid=(L+R)>>1;
	build1(x,rt<<1,L,mid,pos);
	build1(x,rt<<1|1,mid+1,R,pos);
	c[x].t[rt]=max(c[x].t[rt<<1],c[x].t[rt<<1|1]);
}
inline void pushup(int lp,int rp,int x,int rt,int L,int R)
{
	c[x].t[rt]=max(c[lp].t[rt],c[rp].t[rt]);
	if(L==R)return;
	int mid=(L+R)>>1;
	pushup(lp,rp,x,rt<<1,L,mid);
	pushup(lp,rp,x,rt<<1|1,mid+1,R);
}
inline void build(int L,int R,int &p)
{
	p=++cnt;
	if(L==R){build1(p,1,1,n,L);return;}
	int mid=(L+R)>>1;
	build(L,mid,l(p));
	build(mid+1,R,r(p));
	pushup(l(p),r(p),p,1,1,n);
}
inline void ask1(int x,int rt,int L,int R)
{
	if(cy<=L&&yy>=R){ans=max(ans,c[x].t[rt]);return;}
	int mid=(L+R)>>1;
	if(cy<=mid)ask1(x,rt<<1,L,mid);
	if(yy>mid)ask1(x,rt<<1|1,mid+1,R);
}
inline void ask(int L,int R,int p)
{
	if(cx<=L&&xx>=R){ask1(p,1,1,n);return;}
	int mid=(L+R)>>1;
	if(cx<=mid)ask(L,mid,l(p));
	if(xx>mid)ask(mid+1,R,r(p));
	return;
}
int main()
{
	//freopen("1.in","r",stdin);
	n=read();
	m1=read();m2=read();
	rep(1,m1,i)
	{
		int x,y,z;
		x=read();y=read();xx=read();yy=read();z=read();
		a[x][y]+=z;a[xx+1][y]-=z;a[x][yy+1]-=z;a[xx+1][yy+1]+=z;
	}
	rep(1,n,i)rep(1,n,j)a[i][j]+=a[i-1][j]+a[i][j-1]-a[i-1][j-1];
	/*rep(1,n,i)
	{
		rep(1,n,j)
		cout<<a[i][j]<<' ';
		cout<<endl;
	}*/
	build(1,n,root);
	rep(1,m2,i)
	{
		cx=read();cy=read();xx=read();yy=read();
		ans=0;ask(1,n,root);
		printf("%lld\n",ans);
	}
	return 0;
}
  • J 看不懂题目 我是废物。
    题目
posted @ 2022-09-03 21:28  chdy  阅读(16)  评论(0编辑  收藏  举报