24.7.14(板刷数据结构,警钟长鸣)

news2024/11/23 6:31:57

上周六:

算是暑假训练第一天,期末考完了真好

cf round951 div2 D                                                     cf传送门

之前用正解补过,又臭又长,写完就跑了,这次用哈希补一发

思路:目标字符串就两种可能,0开头和1开头,所以可直接算出目标子串的hash值,为num

因为是双哈希,所以东西较多,ha11,第一个1表示正着hash或反着hash,第二个1表示第一套base和mod或第二套,num01,第一个0表示0或1开头,第二个1表示第一套或第二套base,mod

遍历答案,例如字符串长为9,123456789,i为3,那么应该变为 456789 321,用处理出来的hash数组拼凑出来,然后和 num值进行比较即可

代码如下:

const int N=2e5+10;
const int mod1=1e9+7,mod2=998244353;
ll n;
ll p1[N],p2[N],ha11[N],ha12[N],ha21[N],ha22[N];
const int ba1=13331,ba2=131;
void solve(){
	int k; cin >> n >> k;
	string s; cin >> s; s=" "+s;
	ll num01=0,num02=0,num11=0,num12=0;
	p1[0]=p2[0]=1;
	for(int i=1;i<=n;i++){
		p1[i]=p1[i-1]*ba1%mod1;
		p2[i]=p2[i-1]*ba2%mod2;
		ha11[i]=(ha11[i-1]*ba1+s[i])%mod1;
		ha12[i]=(ha12[i-1]*ba2+s[i])%mod2;
		if((i-1)/k&1){
			num01=(num01*ba1+'1')%mod1;
			num02=(num02*ba2+'1')%mod2;
			num11=(num11*ba1+'0')%mod1;
			num12=(num12*ba2+'0')%mod2;
		}else{
			num01=(num01*ba1+'0')%mod1;
			num02=(num02*ba2+'0')%mod2;
			num11=(num11*ba1+'1')%mod1;
			num12=(num12*ba2+'1')%mod2;
		}
	}
	ha21[n+1]=ha22[n+1]=0;
	for(int i=n;i;i--){
		ha21[i]=(ha21[i+1]*ba1+s[i])%mod1;
		ha22[i]=(ha22[i+1]*ba2+s[i])%mod2;
	}
	for(int i=1;i<=n;i++){
		ll ha1=(ha11[n]-ha11[i]*p1[n-i]%mod1+mod1)%mod1*p1[i]%mod1;
		ll ha2=(ha12[n]-ha12[i]*p2[n-i]%mod2+mod2)%mod2*p2[i]%mod2;
		ha1+=(ha21[1]-ha21[i+1]*p1[i]%mod1+mod1)%mod1,ha1%=mod1;
		ha2+=(ha22[1]-ha22[i+1]*p2[i]%mod2+mod2)%mod2,ha2%=mod2;
		if((ha1==num01&&ha2==num02) || (ha1==num11&&ha2==num12)){cout << i << "\n"; return ;}
	}
	cout << "-1\n";
}

上周日:

补cf round 944 div4 F                                                cf传送门

思路:从1到r,二分找范围内点集的上下界,注意判断边界情况

代码如下:

ll n;
void solve(){
	cin >> n;
	ll ans=0;
	for(int i=1;i<=n;i++){
		ll l=0,r=i,res1=-1;
		while(l<=r){
			ll mid=l+r>>1;
			ll y=mid;
			double dis=sqrt(1.0*i*i+1.0*y*y);  // >=r
			if(dis<n) l=mid+1;
			else res1=mid,r=mid-1;
		}
		l=0,r=i;ll res2=-1;
		while(l<=r){
			ll mid=l+r>>1;
			ll y=mid;
			double dis=sqrt(1.0*i*i+1.0*y*y);  // < r+1
			if(dis>=n+1) r=mid-1;
			else res2=mid,l=mid+1;
		}
		if(res1==-1 || res2==-1) continue;
		if(!res1) ans+=4,res1++;
		if(res2==i) ans-=4;
		ans+=(res2-res1+1)*8;
	}
	cout << ans << "\n";
}

板刷构造 1600                                                      cf传送门

题意:构造排列使得任意相邻数的差值在 2-4间

思路:从奇偶性角度考虑,俩相邻奇数或偶数差值即2,先顺着放奇数,然后放一个和最大奇数匹配的偶数即 ma1-3,然后逆着放偶数,最大的差值刚好为4

代码如下:

ll n;

void solve(){
	cin >> n;
	if(n<4){cout << "-1\n"; return ;}
	if(n==4){cout << "3 1 4 2\n"; return ;}
	int ma1=n&1?n:n-1,ma0=n&1?n-1:n;        //最大的奇数和偶数
	int ou=ma1-3;
	for(int i=1;i<=n;i+=2) cout << i << " ";
	cout << ou << " ";
	for(int i=ma0;i;i-=2){
		if(i==ou) continue;
		cout << i << " ";
	}
	cout << "\n";
}

周一:

上午个人赛

补ABC 131 E 构造好题                                                   atc传送门

题意:构造一个图,n个点且满足有 k个点对最短距离为2

思路:n很小,且对边数无限制,可构造一个菊花图,此时满足距离为2的点对数为C n-1 2,即   (n-1)*(n-2)/ 2,这是最多点对的情况,若小于 k输出 -1,若大于 k,在任意两点间连接边,则这两点不再满足即点对数减一,添边直至点对==k

代码如下:

ll n;
void solve(){
	int k; cin >> n >> k;
	ll p=(n-1)*(n-2)/2;
	if(p<k){cout << -1; return ;}
	vector<int>ve[110];
	ll sum=0;
	for(int i=1;i<n;i++) ve[n].push_back(i),sum++;
	for(int i=1;i<n && p>k;i++){
		for(int j=i+1;j<n && p>k;j++){
			ve[i].push_back(j);
			sum++;
			p--;
		}
	}
	cout << sum << "\n";
	for(int i=1;i<=n;i++)
		for(auto j:ve[i]) 
			cout << i << " " << j << "\n";
}

牛客板刷线段树 题一                                           牛客传送门

读错题加上脑子抽了一度卡壳,其实基础线段树题

思路:1到n天,对每个订单检查能否满足,即从 s到 t剩余教室数是否都大于 d,可维护最小值,满足后再更新 s到 t天的剩余教室数

代码如下:

const int N=2e6+10;
ll n;
struct seg_Tree{
#define lc p<<1
#define rc p<<1|1
	struct nod{
		int l,r;
		ll mi,add;
	}t[N];
	ll ql,qr,a[N];
	nod merge(nod a,nod b){
		nod res;
		res.l=a.l,res.r=b.r;
		res.mi=min(a.mi,b.mi);
		res.add=0;
		return res;
	}
	void pushup(int p){t[p]=merge(t[lc],t[rc]);}
	void pushdn(int p){
		if(!t[p].add) return ;
		t[lc].mi+=t[p].add;
		t[rc].mi+=t[p].add;
		t[lc].add+=t[p].add;
		t[rc].add+=t[p].add;
		t[p].add=0;
	}
	void bd(int p,int l,int r){
		t[p]={l,r,0,0};
		if(l==r){
			t[p].mi=a[l];
			return ;
		}
		int m=l+r>>1;
		bd(lc,l,m);
		bd(rc,m+1,r);
		pushup(p);
	}
	void update(int p,int v){
		if(ql<=t[p].l && qr>=t[p].r){
			t[p].mi+=v;
			t[p].add+=v;
			return ;
		}
		int m=t[p].l+t[p].r>>1;
		pushdn(p);
		if(ql<=m) update(lc,v);
		if(qr>m) update(rc,v);
		pushup(p);
	}
	nod query(int p){
		if(ql<=t[p].l && qr>=t[p].r) return t[p];
		int m=t[p].l+t[p].r>>1;
		pushdn(p);
		if(ql>m) return query(rc);
		if(qr<=m) return query(lc);
		return merge(query(lc),query(rc));
	}
	void updt(int l,int r,int v){
		ql=l,qr=r;
		update(1,v);
	}
	ll ask_min(int l,int r){
		ql=l,qr=r;
		return query(1).mi;
	}
#undef lc
#undef rc
}tr;
void solve(){
	int m; cin >> n >> m;
	for(int i=1;i<=n;i++) cin >> tr.a[i];
	tr.bd(1,1,n);
	for(int i=1;i<=m;i++){
		int d,s,t; cin >> d >> s >> t;
		if(tr.ask_min(s,t)<d){cout << "-1\n" << i; return ;}
		tr.updt(s,t,-d);
	}
	cout << 0;
}

板刷数据结构 题二 数贝壳                                        牛客传送门

长见识了

思路:有很多种做法,这里使用的是树状数组。首先需要把查询记录下来离线处理,按 r 排序。 对于一个区间内的相同数字,只关心最右边那个,vi记录数字的最后一次出现位置,例如 1 4 5 1,考虑前三个时,vi【1】=1,vi【4】=2,vi【5】=3,树状数组形为 1 1 1 0,然后下一个查询的 r为4,a【4】已被记录,那么就更新 vi【1】为4,树状数组形为 0 1 1 1。ask( r) - ask( l-1)即为查询的答案

代码如下:

const int N=2e6+10,M=210;
ll n;
ll t[N],a[N];
struct nod{
	int l,r;
	int id,ans;
}q[N];
int vi[N];
int lowbit(int x){return x&-x;}
void add(int x,int v){
	for(int i=x;i<=n;i+=lowbit(i)) t[i]+=v;
}
ll ask(int x){
	ll res=0;
	for(int i=x;i;i-=lowbit(i)) res+=t[i];
	return res;
}
void solve(){
	cin >> n;
	for(int i=1;i<=n;i++) cin >> a[i];
	int m; cin >> m;
	for(int i=1;i<=m;i++){
		cin >> q[i].l >> q[i].r;
		q[i].id=i;
	}
	sort(q+1,q+m+1,[](nod a,nod b){
		return a.r<b.r;
	});
	for(int i=1;i<=m;i++){
		for(int j=q[i-1].r+1;j<=q[i].r;j++){
			if(!vi[a[j]]) add(j,1),vi[a[j]]=j;
			else{
				add(vi[a[j]],-1);
				add(j,1);
				vi[a[j]]=j;
			}
		}
		q[i].ans=ask(q[i].r)-ask(q[i].l-1);
	}
	sort(q+1,q+m+1,[](nod a,nod b){
		return a.id<b.id;
	});
	for(int i=1;i<=m;i++) cout << q[i].ans << "\n";
}

星期二:

板刷数据结构 题三

因为读错题(没注意样例,被耽误了一晚上和半个早上。。

以后读完题记得一定看样例!!!

思路:和数贝壳很像,注意这题一种采了的颜色对答案的贡献只有1! 把询问按 r大小排序,升序处理,把第一次出现的颜色标记一下,但并不赋值,此颜色第二次以及更多次出现时,才对上一次出现的位置+1,且对上上次的位置-1

代码如下:

const int N=2e6+10;
ll n;
ll a[N],t[N];
struct nod{
	int l,r;
	int id,ans;
}q[N];
PII vi[N];
int lowbit(int x){return x&-x;}
void add(int x,int v){
	for(int i=x;i<=n;i+=lowbit(i)) t[i]+=v;
}
ll ask(int x){
	ll res=0;
	for(int i=x;i;i-=lowbit(i)) res+=t[i];
	return res;
}
void solve(){
	int c,m; cin >> n >> c >> m;
	for(int i=1;i<=n;i++) cin >> a[i];
	for(int i=1;i<=m;i++){
		cin >> q[i].l >> q[i].r;
		q[i].id=i;
	}
	sort(q+1,q+m+1,[](nod a,nod b){
		return a.r<b.r;
	});
	for(int i=1;i<=m;i++){
		for(int j=q[i-1].r+1;j<=q[i].r;j++){
			if(!vi[a[j]].first) vi[a[j]].first=j;
			else if(!vi[a[j]].second) add(vi[a[j]].first,1),vi[a[j]].second=j;
			else{
				add(vi[a[j]].first,-1),vi[a[j]].first=vi[a[j]].second;
				add(vi[a[j]].first,1),vi[a[j]].second=j;
			}
		}
		q[i].ans=ask(q[i].r)-ask(q[i].l-1);
	}
	sort(q+1,q+m+1,[](nod a,nod b){
		return a.id<b.id;
	});
	for(int i=1;i<=m;i++) cout << q[i].ans << "\n";
}

最后半小时才知道有个训练赛

ABC 357 C                                                        atc传送门

思路:递归赋值

代码如下:

ll n;
char c[740][740];
void kk(int a,int b,int x,int y){
	if(a==x){c[a][b]='#'; return ;}
	int len=x-a+1;
	len/=3;
	for(int i=0;i<3;i++) kk(a,b+i*len,a+len-1,b+(i+1)*len-1);  //前三个格子
	kk(a+len,b,a+2*len-1,b+len-1);
	for(int i=a+len;i<a+2*len;i++)
		for(int j=b+len;j<b+2*len;j++)
			c[i][j]='.';
	kk(a+len,b+2*len,a+2*len-1,b+3*len-1);                     //中间三个格子
	for(int i=0;i<3;i++) kk(a+2*len,b+i*len,a+3*len-1,b+(i+1)*len-1); //最后三个格子
}
void solve(){
	cin >> n;
	int x=1,y=1;
	for(int i=1;i<=n;i++) x*=3,y*=3;
	kk(1,1,x,y);                        //左上坐标为1,1,右下坐标为x,y
	for(int i=1;i<=x;i++){
		for(int j=1;j<=y;j++) cout << c[i][j];
		cout << "\n";
	}
}

补ABC 325 D                                                      atc传送门

思路:贪心,但比较麻烦。将物品开始 st和结束 ed时间作为pair数据升序排列,在所有 st<=ti的物品中,选择 ed最小的打印,用优先队列实现找最小 ed,每打印一个 ti++,时间++时注意把可开始的物品放入优先队列,若队列为空,则此时无物品可打印,将时间跳转到下一个物品的 st

代码如下:

const int N=2e6+10,M=210;
ll n;
PII a[N];
void solve(){
	cin >> n;
	for(int i=1;i<=n;i++){
		ll t,d; cin >> t >> d;
		a[i].first=t;
		a[i].second=t+d;
	}
	sort(a+1,a+n+1);
	priority_queue<ll,vector<ll>,greater<ll>>pq;
	ll ti=0,ans=0;
	for(int i=1;;ti++){
		if(pq.empty()){
			if(i==n+1) break;
			ti=a[i].first;
		}
		while(i<=n && a[i].first==ti) pq.push(a[i++].second);
		while(!pq.empty() && pq.top()<ti) pq.pop();
		if(!pq.empty()) pq.pop(),ans++;
	}
	cout << ans;
}

补ABC 334 F                                                      atc传送门

思路:dp【i】表示送完了前 i家并回到起点的最短距离,dis【i】为一直走到 i点距离即前缀和 ,ho【i】为与起点的距离

转移式即为:dp【i】= dp【j】+ ho【j+1】+ dis【i】- dis【j+1】+ ho【i】( j >= i-k)

转移式比较麻烦,但推出来后不难想到单调队列优化

最后注意dis【i】是从起点开始算,到 i的距离,而不是第一家小孩开始算

代码如下:

const int N=2e6+10,M=210;
ll n;
ll x[N],y[N];
double dis[N],ho[N];
double dp[N];
void solve(){
	int k; cin >> n >> k;
	int sx,sy; cin >> sx >> sy;
	dis[1]=sqrt((x[1]-sx)*(x[1]-sx)+(y[1]-sy)*(y[1]-sy));
	for(int i=1;i<=n;i++){
		cin >> x[i] >> y[i];
		if(i>1) dis[i]=sqrt((x[i]-x[i-1])*(x[i]-x[i-1])+(y[i]-y[i-1])*(y[i]-y[i-1]));
		dis[i]+=dis[i-1];
		ho[i]=sqrt((x[i]-sx)*(x[i]-sx)+(y[i]-sy)*(y[i]-sy));
	}
	priority_queue<pair<double,int>,vector<pair<double,int>>,greater<pair<double,int>>>pq;
	dp[0]=0;
	pq.push({-dis[1]+ho[1],0});
	for(int i=1;i<=n;i++){
		while(pq.top().second<i-k) pq.pop();
		dp[i]=pq.top().first+dis[i]+ho[i];
		pq.push({dp[i]-dis[i+1]+ho[i+1],i});
	}
	cout << fixed << setprecision(8) << dp[n];
}

补 ABC 299 E                                                        atc传送门

思路:除了必须白色的点,全涂为黑色,然后用 bfs来check是否合法,用 dfs进行check会wa,  目前不知道其原因

dfs错误的原因想到了,x和dis代表的是点以及和起点的距离,但因dfs是深度优先搜索,dis会出错

代码如下:

ll n;
vector<int>ve[2020];
int p[2020],d[2020];
string s;
bool vi[2020];
bool ifd;
bool dfs(int x,int dis){
	if(dis>0 && s[x-1]=='1'){ifd=0; return 0;}
	if(dis==0) return s[x-1]=='1';
	vi[x]=1;
	bool if1=0;
	for(auto i:ve[x])
		if(!vi[i]) vi[i]=1,if1|=dfs(i,dis-1);
	if(!ifd) return 0;
	return if1;
}
bool bfs(int x,int d){
	queue<PII>q;
	q.push({x,0});
	vi[x]=1;
	while(!q.empty()){
		auto [x,y]=q.front(); q.pop();
		if(y==d){
			if(s[x-1]=='1') return 1;
			continue;
		}
		for(auto i:ve[x])
			if(!vi[i]) vi[i]=1,q.push({i,y+1});
	}
	return 0;
}
void solve(){
	int m; cin >> n >> m;
	for(int i=1;i<=m;i++){
		int u,v; cin >> u >> v;
		ve[u].push_back(v);
		ve[v].push_back(u);
	}
	int k; cin >> k;
	set<int>mtw;
	for(int i=1;i<=k;i++){
		cin >> p[i] >> d[i];
		queue<PII>q;
		memset(vi,0,sizeof vi);
		q.push({p[i],0});
		vi[p[i]]=1;
		while(!q.empty()){
			auto [x,y]=q.front(); q.pop();
			if(y==d[i]) continue;
			mtw.insert(x);
			for(auto j:ve[x])
				if(!vi[j]) vi[j]=1,q.push({j,y+1});
		}
	}
	if(!k){cout << "Yes\n"; for(int i=1;i<=n;i++) cout << 1; return ;}
	for(int i=1;i<=n;i++) s.append("0");
	for(int i=1;i<=n;i++) if(mtw.find(i)==mtw.end()) s[i-1]='1';
	for(int i=1;i<=k;i++){
		memset(vi,0,sizeof vi);
		ifd=1;
		if(!bfs(p[i],d[i])){cout << "No"; return ;}
	}
	cout << "Yes\n" << s;
}

星期三:

补 hdu1421                                                           smu传送门

很普通的dp,赛时没出是我的问题

思路:dp【i】【j】表示考虑到前 i个物品,选了 j对的最小疲劳

有一个比较显然的结论(但我没想到)的是,物品配对的选择一定是排序后两两相邻着拿

转移式:dp【i】【j】= min( dp【i-2】【j-1】+ ( a【i】- a【i-1】)^2,dp【i-1】【j】) 

代码如下:

ll n;
int a[2020];
int dp[2020][1010];
void solve(){
	int k;
	while(cin >> n >> k){
		for(int i=1;i<=n;i++) cin >> a[i];
		sort(a+1,a+n+1);
		for(int i=0;i<=n;i++)
			for(int j=1;j<=k;j++) dp[i][j]=1e9;
		for(int i=2;i<=n;i++){
			for(int j=1;j*2<=i;j++){
				dp[i][j]=min(dp[i-2][j-1]+(a[i]-a[i-1])*(a[i]-a[i-1]),dp[i-1][j]);
			}
		}
		cout << dp[n][k] << "\n";
	}
}

补ABC 200 D                                                           atc传送门

之前没接触过鸽巢原理,现在遇到了一道与之相关的题,真是学到了

思路:n为200,看似很小,但如果要纯暴力又肯定不行。根据鸽巢原理,根据对200的模数把序列分类,最多需要多少序列就能确定一定有模数相同的序列呢?201个序列足矣,长为 n的序列存在 2^n-1个非空子序列,所以若n>8,也只需要对前8个进行暴力分类,就一定有解

代码如下:

ll n;
ll a[220];
void solve(){
	cin >> n;
	for(int i=1;i<=n;i++) cin >> a[i];
	map<int,vector<int>>mp;
	int cnt=0;
	vector<int>ve[220];
	int len=min(8ll,n);
	for(int mask=1;mask<1<<len;mask++){
		ll sum=0;
		vector<int>tp;
		for(int j=0;j<len;j++) if(mask&1<<j) sum+=a[j+1],tp.push_back(j+1);
		mp[++cnt]=tp;
		ve[sum%200].push_back(cnt);                    //序列的编号
	}
	for(int i=0;i<200;i++)
		if(ve[i].size()>1){
			cout << "Yes\n";
			cout << mp[ve[i][0]].size() << " ";
			for(auto j:mp[ve[i][0]]) cout << j << " ";
			cout << "\n";
			cout << mp[ve[i][1]].size() << " ";
			for(auto j:mp[ve[i][1]]) cout << j << " ";
			return ;
		}
	cout << "No";
}

补ABC 204 E                                                     atc传送门

思路:dp【i】表示到达 i点的最短时间,dfs不能实现转移,需要迪杰斯特拉

dp【v】= min( t + C + D/( t+1),dp【v】),t >= dp【u】

把 t+1用 x来表示,dp【v】= x + D/x + C - 1,x >= dp【u】+1

如何求 x+D/x的最小值呢,试过三分,但整形的三分会出错,结论是 x=sqrt(D)四舍五入时最小

代码如下:

const int N=3e5+10;
ll n;
struct nod{
	int v;
	ll c,d;
};
vector<nod>ve[N];
ll dp[N];
bool vi[N];
void dij(){
	memset(dp,0x3f,sizeof dp);
	priority_queue<PII,vector<PII>,greater<PII>>pq;
	pq.push({0,1});
	dp[1]=0;
	while(!pq.empty()){
		auto [t,u]=pq.top(); pq.pop();
		if(vi[u]) continue;
		vi[u]=1;
		for(auto nd:ve[u]){
			ll v=nd.v,c=nd.c,d=nd.d;
			ll x=round(sqrt(d));
			x=max(t+1,x);
			ll w=x+d/x+c-1;
			if(w<dp[v]){
				dp[v]=w;
				pq.push({dp[v],v});
			}
		}
	}
}
void solve(){
	int m; cin >> n >> m;
	for(int i=1;i<=m;i++){
		int a,b,c,d; cin >> a >> b >> c >> d;
		ve[a].push_back({b,c,d});
		ve[b].push_back({a,c,d});
	}
	dij();
	if(dp[n]>1e18) cout << -1;
	else cout << dp[n];
}

补ABC 202 E                                                      atc传送门

题意:给一棵树,q次询问,每次求 u子树上有多少深度为 d的点

思路:用时间戳解决,若 v是 u的子树上的点,则满足 in【u】<= in【v】< out【v】<= out【u】,按深度来存点,在深度数组里二分查找满足条件的点集区间(只存 in【x】值

以上关于时间戳的结论在 atc此题的题解中有较详细的证明:

代码如下:

const int N=3e5+10;
ll n;
vector<int>ve[N],dep[N];
int in[N],out[N],timer;
void dfs(int x,int d){
	in[x]=++timer;
	dep[d].push_back(in[x]);
	for(auto v:ve[x]) dfs(v,d+1);
	out[x]=++timer;
}
void solve(){
	cin >> n;
	for(int i=2;i<=n;i++){
		int p; cin >> p;
		ve[p].push_back(i);
	}
	dfs(1,0);
	int q; cin >> q;
	while(q--){
		int u,d; cin >> u >> d;
		auto r=lower_bound(dep[d].begin(),dep[d].end(),out[u]);
		auto l=lower_bound(dep[d].begin(),dep[d].end(),in[u]);
		cout << r-l << "\n";
	}
}

板刷数据结构 题四 数据结构                                牛客传送门

思路:之前做过维护乘和加的线段树,这次多了一个平方和,需要推下式子,懒标记注意先乘再加

代码如下:

const int N=3e5+10,M=210;
ll n;
struct seg_Tree{
#define lc p<<1
#define rc p<<1|1
	struct nod{
		int l,r;
		ll sum,sum2;
		ll add,mul;
	}t[N<<2];
	int ql,qr,qop;
	ll qv,a[N];
	nod merge(nod a,nod b){
		nod res;
		res.l=a.l,res.r=b.r;
		res.sum=a.sum+b.sum;
		res.sum2=a.sum2+b.sum2;
		res.add=0;
		res.mul=1;
		return res;
	}
	void pushup(int p){t[p]=merge(t[lc],t[rc]);}
	void pushdn(int p){
		if(t[p].mul!=1){
			t[lc].sum2*=t[p].mul*t[p].mul;
			t[rc].sum2*=t[p].mul*t[p].mul;
			t[lc].sum*=t[p].mul;
			t[rc].sum*=t[p].mul;
			t[lc].mul*=t[p].mul;
			t[rc].mul*=t[p].mul;
			t[lc].add*=t[p].mul;
			t[rc].add*=t[p].mul;             //注意对add的影响不要遗漏
			t[p].mul=1;
		}
		if(t[p].add){
			t[lc].sum2+=2*t[lc].sum*t[p].add+(t[lc].r-t[lc].l+1)*t[p].add*t[p].add;
			t[rc].sum2+=2*t[rc].sum*t[p].add+(t[rc].r-t[rc].l+1)*t[p].add*t[p].add;
			t[lc].sum+=(t[lc].r-t[lc].l+1)*t[p].add;
			t[rc].sum+=(t[rc].r-t[rc].l+1)*t[p].add;
			t[lc].add+=t[p].add;
			t[rc].add+=t[p].add;
			t[p].add=0;
		}
	}
	void bd(int p,int l,int r){
		t[p]={l,r,0,0,0,1};
		if(l==r){
			t[p].sum=a[l];
			t[p].sum2=a[l]*a[l];
			return ;
		}
		int mid=l+r>>1;
		bd(lc,l,mid);
		bd(rc,mid+1,r);
		pushup(p);
	}
	void update(int p){
		if(ql<=t[p].l && qr>=t[p].r){
			if(qop==1){                        //区间加
				t[p].sum2+=2*t[p].sum*qv+(t[p].r-t[p].l+1)*qv*qv;
				t[p].sum+=(t[p].r-t[p].l+1)*qv;
				t[p].add+=qv;
				return ;
			}else{                             //区间乘
				t[p].sum2*=qv*qv;
				t[p].sum*=qv;
				t[p].mul*=qv;
				t[p].add*=qv;
				return ;
			}
		}
		int mid=t[p].l+t[p].r>>1;
		pushdn(p);
		if(ql<=mid) update(lc);
		if(qr>mid) update(rc);
		pushup(p);
	}
	nod query(int p){
		if(ql<=t[p].l && qr>=t[p].r) return t[p];
		int mid=t[p].l+t[p].r>>1;
		pushdn(p);
		if(ql>mid) return query(rc);
		if(qr<=mid) return query(lc);
		return merge(query(lc),query(rc));
	}
	void updt(int l,int r,int op,ll v){
		ql=l,qr=r;
		qop=op,qv=v;
		update(1);
	}
	ll ask_sum(int l,int r){
		ql=l,qr=r;
		return query(1).sum;
	}
	ll ask_sum2(int l,int r){
		ql=l,qr=r;
		return query(1).sum2;
	}
}tr;
void solve(){
	int q; cin >> n >> q;
	for(int i=1;i<=n;i++) cin >> tr.a[i];
	tr.bd(1,1,n);
	while(q--){
		int op; cin >> op;
		if(op==1 || op==2){
			int l,r; cin >> l >> r;
			if(op==1) cout << tr.ask_sum(l,r) << "\n";
			if(op==2) cout << tr.ask_sum2(l,r) << "\n";
		}
		if(op==3 || op==4){
			int l,r;ll x; cin >> l >> r >> x;
			if(op==3) tr.updt(l,r,2,x);
			if(op==4) tr.updt(l,r,1,x);
		}
	}
}

星期四:

板刷数据结构 题五                                                    牛客传送门

思路:和上一题有点像,注意运算中时刻%P,不然会爆 ll

代码如下:

const int N=3e5+10,M=210;
ll n;
int P;
struct seg_Tree{
#define lc p<<1
#define rc p<<1|1
	struct nod{
		int l,r;
		ll sum,sum2;
		ll add,mul;
	}t[N<<2];
	int ql,qr,qop;
	ll qv,a[N];
	nod merge(nod a,nod b){
		nod res;
		res.l=a.l,res.r=b.r;
		res.sum=(a.sum+b.sum)%P;
		res.sum2=(a.sum2+b.sum2+a.sum*b.sum%P)%P;
		res.add=0;
		res.mul=1;
		return res;
	}
	void pushup(int p){t[p]=merge(t[lc],t[rc]);}
	void pushdn(int p){
		if(t[p].mul!=1){
			t[lc].sum2*=t[p].mul*t[p].mul%P,t[lc].sum2%=P;
			t[rc].sum2*=t[p].mul*t[p].mul%P,t[rc].sum2%=P;
			t[lc].sum*=t[p].mul,t[lc].sum%=P;
			t[rc].sum*=t[p].mul,t[rc].sum%=P;
			t[lc].mul*=t[p].mul,t[lc].mul%=P;
			t[rc].mul*=t[p].mul,t[rc].mul%=P;
			t[lc].add*=t[p].mul,t[lc].add%=P;
			t[rc].add*=t[p].mul,t[rc].add%=P;
			t[p].mul=1;
		}
		if(t[p].add){
			t[lc].sum2+=t[lc].sum*(t[lc].r-t[lc].l)%P*t[p].add%P+(t[lc].r-t[lc].l+1)*(t[lc].r-t[lc].l)/2*t[p].add%P*t[p].add,t[lc].sum2%=P;
			t[rc].sum2+=t[rc].sum*(t[rc].r-t[rc].l)%P*t[p].add%P+(t[rc].r-t[rc].l+1)*(t[rc].r-t[rc].l)/2*t[p].add%P*t[p].add,t[rc].sum2%=P;
			t[lc].sum+=(t[lc].r-t[lc].l+1)*t[p].add%P,t[lc].sum%=P;
			t[rc].sum+=(t[rc].r-t[rc].l+1)*t[p].add%P,t[rc].sum%=P;
			t[lc].add+=t[p].add,t[lc].add%=P;
			t[rc].add+=t[p].add,t[rc].add%=P;
			t[p].add=0;
		}
	}
	void bd(int p,int l,int r){
		t[p]={l,r,0,0,0,1};
		if(l==r){
			t[p].sum=a[l];
			return ;
		}
		int mid=l+r>>1;
		bd(lc,l,mid);
		bd(rc,mid+1,r);
		pushup(p);
	}
	void update(int p){
		if(ql<=t[p].l && qr>=t[p].r){
			if(qop==1){                          //区间加
				t[p].sum2+=t[p].sum*(t[p].r-t[p].l)%P*qv%P+(t[p].r-t[p].l+1)*(t[p].r-t[p].l)/2%P*qv%P*qv%P,t[p].sum2%=P;
				t[p].sum+=(t[p].r-t[p].l+1)*qv%P,t[p].sum%=P;
				t[p].add+=qv,t[p].add%=P;
			}else{                               //区间乘
				t[p].sum2*=qv*qv%P,t[p].sum2%=P;
				t[p].sum*=qv,t[p].sum%=P;
				t[p].mul*=qv,t[p].mul%=P;
				t[p].add*=qv,t[p].add%=P;
			}
			return ;
		}
		int mid=t[p].l+t[p].r>>1;
		pushdn(p);
		if(ql<=mid) update(lc);
		if(qr>mid) update(rc);
		pushup(p);
	}
	nod query(int p){
		if(ql<=t[p].l && qr>=t[p].r) return t[p];
		int mid=t[p].l+t[p].r>>1;
		pushdn(p);
		if(ql>mid) return query(rc);
		if(qr<=mid) return query(lc);
		return merge(query(lc),query(rc));
	}
	void updt(int l,int r,int op,ll v){
		ql=l,qr=r;
		qop=op,qv=v;
		update(1);
	}
	ll ask_sum(int l,int r){
		ql=l,qr=r;
		return query(1).sum;
	}
	ll ask_sum2(int l,int r){
		ql=l,qr=r;
		return query(1).sum2;
	}
}tr;
void solve(){
	int m; cin >> n >> m >> P;
	for(int i=1;i<=n;i++) cin >> tr.a[i];
	tr.bd(1,1,n);
	while(m--){
		int op; cin >> op;
		if(op==3){
			int l,r; cin >> l >> r;
			cout << tr.ask_sum2(l,r)%P << "\n";
		}else{
			int l,r,v; cin >> l >> r >> v;
			tr.updt(l,r,op,v);
		}
	}
}

下午暑假友谊赛热身1

贴个D                                                               atc传送门

题意:将 a数组切三刀分成四段,使四段中的最大sum值和最小sum值差值最小

思路:注意到切三刀这个操作,先考虑能不能枚举中间那刀,答案是可以的,两边的最佳切法为将值尽量对半开,二分lower_bound找到切点,因为lower_bound是大于等于值的一半,所以注意检查切点往左移一位是否更优

代码如下:

const int N=3e5+10;
ll n;
ll a[N];
void solve(){
	cin >> n;
	for(int i=1;i<=n;i++){
		cin >> a[i];
		a[i]+=a[i-1];
	}
	ll ans=1e18;
	for(int mid=2;mid<=n-2;mid++){
		ll l=a[mid],r=a[n]-a[mid];
		int i=lower_bound(a+1,a+n+1,l/2)-a;
		if(i>1 && abs(a[mid]-a[i]*2)>abs(a[mid]-a[i-1]*2)) i--;
		int j=lower_bound(a+1,a+n+1,a[mid]+r/2)-a;
		if(j>mid+1 && abs(a[n]+a[mid]-a[j]*2)>abs(a[n]+a[mid]-a[j-1]*2)) j--;
		ll ma=max({a[i],a[mid]-a[i],a[j]-a[mid],a[n]-a[j]});
		ll mi=min({a[i],a[mid]-a[i],a[j]-a[mid],a[n]-a[j]});
		ans=min(ma-mi,ans);
	}
	cout << ans;
}

星期五:

补cf round731 div3                                                   cf传送门

思路:注意到一部空调可以对两端都造成影响,遇到这种类型的题,优先考虑把左端和右端分开考虑。l【i】表示只考虑左边空调影响的最低温度,r【i】表示只考虑右边空调影响的最低温度

l【i】= min(l【i-1】+ 1,l【i】),r【i】= min(r【i+1】+1,r【i】),答案取更小值

代码如下:

const int N=3e5+10,M=210;
ll n;
int a[N],t[N];
int l[N],r[N];
void solve(){
	int k; cin >> n >> k;
	for(int i=0;i<=n+1;i++) l[i]=r[i]=2e9;
	for(int i=1;i<=k;i++) cin >> a[i];
	for(int i=1;i<=k;i++){
		cin >> t[i];
		l[a[i]]=r[a[i]]=t[i];
	}
	for(int i=1;i<=n;i++)
		l[i]=min(l[i-1]+1,l[i]);
	for(int i=n;i;i--)
		r[i]=min(r[i+1]+1,r[i]);
	for(int i=1;i<=n;i++) cout << min(l[i],r[i]) << " \n"[i==n];
}

补cf round 957 div3 D                                           cf传送门

很恶心一道模拟,但放上来的重点不是这个,而是提醒自己特判要等到输入完成之后!!!

    int m,k; cin >> n >> m >> k;
	if(m>n){cout << "YES\n"; return ;}
	string s; cin >> s; s=" "+s;

此为错误代码,也是我赛时写的,将m>n的特判放到 cin >> s后,就能过了

!!!!!!!!!!!!!!!!!!警钟长鸣!!!!!!!!!!!!!!!!!!!!!

板刷数据结构 H                                               牛客传送门

思路:维护全局最大值,然后线段树上二分

需要注意两点,第一点是merge时,res不能嗯取 a,b的最大值,取 ma1的前提是子节点ma2>0,第二点是输出 -1后是 contnue而不是 return

代码如下:

const int N=3e5+10;
ll n;
int m,k;
struct seg_Tree{
#define lc p<<1
#define rc p<<1|1
	struct nod{
		int l,r;
		ll ma1,ma2;
	}t[N<<2];
	int ql,qr,qv;
	nod merge(nod a,nod b){
		nod res;
		res.l=a.l,res.r=b.r;
		if(a.ma2 && b.ma2) res.ma1=max(a.ma1,b.ma1),res.ma2=1;
		else if(a.ma2) res.ma1=a.ma1,res.ma2=1;
		else if(b.ma2) res.ma1=b.ma1,res.ma2=1;
		else res.ma1=res.ma2=0;
		return res;
	}
	void pushup(int p){t[p]=merge(t[lc],t[rc]);}
	void bd(int p,int l,int r){
		t[p]={l,r,m,k};
		if(l==r) return ;
		int mid=l+r>>1;
		bd(lc,l,mid);
		bd(rc,mid+1,r);
	}
	void update(int p){
		if(ql<=t[p].l && qr>=t[p].r){
			t[p].ma1-=qv;
			t[p].ma2--;
			return ;
		}
		int mid=t[p].l+t[p].r>>1;
		if(ql<=mid) update(lc);
		if(qr>mid) update(rc);
		pushup(p);
	}
	void updt(int l,int r,int v){
		ql=l,qr=r;
		qv=v;
		update(1);
	}
	int fnd(int p,int a){
		if(t[p].l==t[p].r) return t[p].l;
		if(t[lc].ma1>=a && t[lc].ma2>0) return fnd(lc,a);
		return fnd(rc,a);
	}
}tr;
void solve(){
	cin >> n >> m >> k;
	tr.bd(1,1,n);
	for(int i=1;i<=n;i++){
		int a; cin >> a;
		if(tr.t[1].ma1<a || tr.t[1].ma2<=0){cout << "-1\n"; continue;}
		int res=tr.fnd(1,a);
		tr.updt(res,res,a);
		cout << res << "\n";
	}
}

星期六:

上午友谊赛

贴个ABC123 D                                                           atc传送门

和 hdoj的大雪球很像

思路:狠狠地二分求出第 k个的值,然后把大于此值的存入,排序输出,操作有点复杂,写了挺久

代码如下:

ll n;
ll a[1010],b[1010],c[1010];
void solve(){
	ll x,y,z,pq; cin >> x >> y >> z >> pq;
	for(int i=1;i<=x;i++) cin >> a[i];
	for(int i=1;i<=y;i++) cin >> b[i];
	for(int i=1;i<=z;i++) cin >> c[i];
	sort(a+1,a+x+1);
	sort(b+1,b+y+1);
	sort(c+1,c+z+1);
	ll l=a[1]+b[1]+c[1],r=a[x]+b[y]+c[z],res=0;
	while(l<=r){                       //二分出第 k个的体积
		ll mid=l+r>>1;
		ll sum=0;
		for(int i=1;i<=x;i++){
			for(int j=1;j<=y;j++){
				int k=lower_bound(c+1,c+z+1,mid-a[i]-b[j])-c;
				sum+=z-k+1;                              //算出大于此体积的个数
			}
		}
		if(sum>=pq) res=mid,l=mid+1;
		else r=mid-1;
	}
	vector<ll>ans; ll cnt=0;
	for(int i=x;i;i--){
		if(a[i]+b[y]+c[z]<res) break;
		for(int j=y;j;j--){
			if(a[i]+b[j]+c[z]<res) break;
			for(int k=z;k;k--){
				if(a[i]+b[j]+c[k]<res) break;
				ans.push_back(a[i]+b[j]+c[k]);
				cnt++;
				if(cnt>pq*1000) break;        //塞少了会wa
			}
			if(cnt>pq*1000) break;
		}
		if(cnt>pq*1000) break;
	}
	sort(ans.begin(),ans.end(),greater<>());
	for(int i=0;i<pq;i++) cout << ans[i] << "\n";
}

贴个ABC204 D                                                        atc传送门

思路:典题,正解类似于背包,一维枚举物品,二维枚举体积,这里是dfs加个记忆化

代码如下:

const int N=2e5+10,M=210;
ll n;
int t[1010];
ll ans;
ll dp[110][N];
ll dfs(int x,int sum1,int sum2){
	if(x>n) return max(sum1,sum2);
	if(max(sum1,sum2)>=ans) return dp[x][sum1]=INT_MAX;
	if(dp[x][sum1]!=-1) return dp[x][sum1];
	if(dp[x][sum2]!=-1) return dp[x][sum2];
	ll res=0;
	res=min(dfs(x+1,sum1+t[x],sum2),dfs(x+1,sum1,sum2+t[x]));
	return dp[x][sum1]=res;
}
void solve(){
	cin >> n;
	for(int i=1;i<=n;i++) cin >> t[i];
	sort(t+1,t+n+1,greater<>());
	int sum1=0,sum2=0;
	for(int i=1;i<=n;i++){
		if(sum1<sum2) sum1+=t[i];
		else sum2+=t[i];
	}
	ans=max(sum1,sum2);
	memset(dp,-1,sizeof dp);
	ans=min(dfs(1,0,0),ans);
	cout << ans;
}

补cf round734 D1                                                   cf传送门

题意:在n*m的格子里放k个1*2的骨牌,剩下的放 2*1的,能否放满

思路:分类讨论,n和m的奇偶性有三种情况

n和m都为偶,k奇数NO,偶数YES

n为奇,考虑将其转化为第一种情况,先用 m/2个横牌填满一行,若填不了也肯定NO

m为奇,也考虑如何转化为第一种情况,用 n/2个竖牌填一列 (判断 k的大小),再判断 k奇偶

代码如下:

ll n;
void solve(){
	ll m,k; cin >> n >> m >> k;
	if(n!=2 && k==n*m/2-1){cout << "NO\n"; return ;}
	if(!(n&1) && !(m&1)){
		if(k&1) cout << "NO\n";
		else cout << "YES\n";
	}else if(!(n&1)){
		if(k>n*m/2-n/2) cout << "NO\n";
		else if(k&1) cout << "NO\n";
		else cout << "YES\n";
	}else{
		if(k>=m/2){
			k-=m/2;
			if(k&1) cout << "NO\n";
			else cout << "YES\n";
		}else cout << "NO\n";
	}
}

补ABC 067 D                                                          atc传送门

思路:容易想到两人应该先抢占 1-n的简单路径,抢完后谁能涂的点多谁就赢

dis【i】表示 i到俩人的距离,disb【i】<= disw【i】,此点就是F的,否则S的

代码如下:

const int N=2e5+10,M=210;
ll n;
vector<int>ve[N];
int disb[N],disw[N];
int sumb,sumw;
void dfsb(int x,int f){
	for(int v:ve[x]){
		if(v==f) continue;
		disb[v]=disb[x]+1;
		dfsb(v,x);
	}
}
void dfsw(int x,int f){
	for(int v:ve[x]){
		if(v==f) continue;
		disw[v]=disw[x]+1;
		dfsw(v,x);
	}
}
void painb(int x,int f){
	if(disb[x]>disw[x]) return ;
	sumb++;
	for(int v:ve[x]){
		if(v==f) continue;
		painb(v,x);
	}
}
void painw(int x,int f){
	if(disw[x]>=disb[x]) return ;
	sumw++;
	for(int v:ve[x]){
		if(v==f) continue;
		painw(v,x);
	}
}
void solve(){
	cin >> n;
	for(int i=1;i<n;i++){
		int a,b; cin >> a >> b;
		ve[a].push_back(b);
		ve[b].push_back(a);
	}
	dfsb(1,0);
	dfsw(n,0);
	painb(1,0);
	painw(n,0);
	if(sumb<=sumw) cout << "Snuke";
	else cout << "Fennec";
}

补cf round760 div3 F                                           cf传送门

思路:第一眼可能会让人摸不着头脑,但手操下操作会发现,x能变为的数是十分有限的

若加0翻转,实际等于去除末尾的0再翻转,连续的有效操作次数最多为2

若加1翻转,等于翻转后加一个高位的1,这样操作在60次后就一定会超过1e18

所以可直接暴力模拟

代码如下:

string to_s(ll x){
	string s;
	while(x){
		if(x&1) s.append("1");
		else s.append("0");
		x>>=1;
	}
	reverse(s.begin(),s.end());
	return s;
}
void solve(){
	ll x,y; cin >> x >> y;
	string sx=to_s(x),sy=to_s(y);
	set<string>st;
	st.insert(sx);
	queue<string>qu;
	qu.push(sx);
	while(!qu.empty()){
		string t=qu.front(); qu.pop();
		if(t.size()>60) continue;
		string xs=t;
		while(xs.back()=='0') xs.pop_back();
		reverse(xs.begin(),xs.end());
		if(st.find(xs)==st.end()){
			st.insert(xs);
			qu.push(xs);
		}
		t.append("1");
		reverse(t.begin(),t.end());
		if(st.find(t)==st.end()){
			st.insert(t);
			qu.push(t);
		}
	}
	if(st.find(sy)!=st.end()) cout << "YES";
	else cout << "NO";
}

周日:

补 ABC207 E                                                         atc传送门

思路:dp【i】【j】表示考虑到第 i个元素,分成 j段的方案数,朴素转移复杂度为 O(n^3)

dp【i】【j】从 dp【k】【j-1】转移的条件是 ( a【i】- a【k】)% j == 0,也就是 a【i】与 a【k】同模 j,那么可以用 sum提前存下分成 j-1段及其对 j模数为 a【i】%j的总方案数(有点抽象

代码如下:

const int mod=1e9+7;
ll n;
ll a[3030];
ll dp[3030][3030];
ll sum[3030][3030];
void solve(){
	cin >> n;
	for(int i=1;i<=n;i++){
		cin >> a[i];
		a[i]+=a[i-1];
	}
	for(int i=1;i<=n;i++){
		dp[i][1]=1;
		for(int j=2;j<=i;j++)
			dp[i][j]=sum[j][a[i]%j];
		for(int j=1;j<=n;j++)
			(sum[j][a[i]%j]+=dp[i][j-1])%=mod;
	}
	ll ans=0;
	for(int i=1;i<=n;i++) (ans+=dp[n][i])%=mod;
	cout << ans;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1926451.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2022睿抗CAIP-编程技能赛-本科组省赛(c++)(未完结)

RC-u1 不要浪费金币 模拟 AC: #include<iostream> #define int long long using namespace std; const int N1e35; int n,m,p[N],ans; signed main(){cin>>n>>m;for(int i1;i<n;i) cin>>p[i];int sum0;for(int i1;i<n;i){if(sump[i]<m) sump…

昇思25天学习打卡营第21天|ResNet50迁移学习

在实际应用场景中&#xff0c;由于训练数据集不足&#xff0c;所以很少有人会从头开始训练整个网络。普遍的做法是&#xff0c;在一个非常大的基础数据集上训练得到一个预训练模型&#xff0c;然后使用该模型来初始化网络的权重参数或作为固定特征提取器应用于特定的任务中。 …

STM32MP135裸机编程:BOOT跳转到APP前关闭所有中断、清除所有中断挂起标志操作方法

0 前言 一般来说&#xff0c;MCU/SOC的BOOT在跳转到APP前都需要进行环境清理的操作&#xff0c;其中必须进行的一项操作便是关闭所有中断、清除所有中断挂起标志。本文介绍基于STM32MP135裸机编程下关闭所有中断、清除所有中断挂起标志的操作方法。 1 操作方法 STM32MP135裸…

缓存与分布式锁

一、缓存 1、缓存使用 为了系统性能的提升&#xff0c;我们一般都会将部分数据放入缓存中&#xff0c;加速访问。 适合放入缓存的数据有&#xff1a; 即时性、数据一致性要求不高的&#xff1b;访问量大且更新频率不高的数据。 在开发中&#xff0c;凡是放入缓存中的数据我们都…

机器人前沿--PalmE:An Embodied Multimodal Language Model 具身多模态大(语言)模型

首先解释这篇工作名称Palm-E&#xff0c;发表时间为2023.03&#xff0c;其中的Palm是谷歌内部在2022.04开发的大语言模型&#xff0c;功能类似ChatGPT&#xff0c;只是由于各种原因没有那样火起来&#xff0c;E是Embodied的首字母&#xff0c;翻译过来就是具身多模态大语言模型…

基于5个K7的多FPGA PCIE总线架构的高性能数据预处理平台

板载FPGA实时处理器&#xff1a;XCKU060-2FFVA15172个QSFP光纤接口&#xff0c;最大支持10Gbps/lane板载DMA控制器&#xff0c;能实现双向DMA高速传输支持x8 PCIE主机接口&#xff0c;系统带宽5GByte/s1个R45自适应千兆以太网口1个FMC子卡扩展接口 基于PCIE总线架构的高性能数据…

c++包管理器

conan conan search&#xff0c;查看网络库 conan profile detect&#xff0c;生成缓存信息conan new cmake_exe/cmake_lib&#xff0c;创建cmakelists.txtconan install .&#xff0c;执行Conanfile.txt中的配置&#xff0c;生成相关的bat文件 项目中配置Conanfile.txt(或者…

【学习笔记】无人机(UAV)在3GPP系统中的增强支持(十一)-无人机服务可用性用例需求

引言 本文是3GPP TR 22.829 V17.1.0技术报告&#xff0c;专注于无人机&#xff08;UAV&#xff09;在3GPP系统中的增强支持。文章提出了多个无人机应用场景&#xff0c;分析了相应的能力要求&#xff0c;并建议了新的服务级别要求和关键性能指标&#xff08;KPIs&#xff09;。…

口袋算法的示例

原理 口袋算法是感知器(Perceptron)算法的一种改进。感知器算法是一种线性分类算法,但在训练数据不是线性可分的情况下,它可能无法收敛,即无法找到一个线性分类器来正确分类所有的训练样本。为了解决这个问题,口袋算法引入了一个"口袋"(Pocket),用来存储迄…

Redis② —— Redis线程模型

1. Redis是单线程吗&#xff1f; 指 接受客户请求 --> 解析请求 --> 进行数据读写操作 --> 发送数据给客户端 这个过程由一个主线程完成redis程序并不是单线程的&#xff0c;在启动时会启动后台进程 2.6之前启动两个后台线程&#xff0c;分别处理关闭文件、AOF刷盘4.…

Go 语言返回组装数据

文章id 文章标题 ..... 分类 字段 &#xff1a;[分类名&#xff0c;分类描述 .... ]标签字段 : [标签名, 标签id ..... ]type ArticleWithCategoryLabel struct {system.SysArticleCategoryName system.SysCategorie json:"category_name"LabelName system.SysLab…

CSS选择器(1)

以内部样式表编写CSS选择器&#xff0c;其主要编写在<head></head>元素里&#xff0c;通过<style></style>标签来定义内部样式表。 基本语法为&#xff1a; 选择器{ 声明块 } 声明块&#xff1a;是由一对大括号括起来&#xff0c;声明块中是一个一个的…

23种设计模式之责任链模式

责任链模式 1、定义 避免将一个请求的发送者与接受者耦合在一起&#xff0c;让多个对象都有机会处理请求。将接受请求的对象连接成一条链&#xff0c;并且沿着这条链传递请求&#xff0c;直到有一个对象能够处理它为止 2、责任链模式结构 Handler(抽象处理者)&#xff1a;定…

使用Python和MediaPipe实现手势控制音量(Win/Mac)

1. 依赖库介绍 OpenCV OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个开源的计算机视觉和机器学习软件库。它包含了数百个计算机视觉算法。 MediaPipe MediaPipe是一个跨平台的机器学习解决方案库&#xff0c;可以用于实时人类姿势估计、手势识…

什么是im即时通讯?WorkPlus im即时通讯私有化部署安全可控

IM即时通讯是Instant Messaging的缩写&#xff0c;指的是一种实时的、即时的电子信息交流方式&#xff0c;也被称为即时通讯。它通过互联网和移动通信网络&#xff0c;使用户能够及时交换文本消息、语音通话、视频通话、文件共享等信息。而WorkPlus im即时通讯私有化部署则提供…

[MySQL][表的约束][二][主键][自增长][唯一键][外键]详细讲解

目录 1.主键2.自增长1.是什么&#xff1f;2.索引 3.唯一键4.外键1.为什么&#xff1f;2.是什么&#xff1f;3.如何理解外键约束&#xff1f; 5.综合案例 -- 阅读 1.主键 主键&#xff1a;primary key用来唯一的约束该字段里面的数据&#xff0c;不能重复&#xff0c;不能为空&a…

Linux系列--命令详解

目录 一、Linux资源管理方式 二、查询类型命令详解 三、文件管理类型命令详解 四、文件压缩与解压 五、文件编辑 六、系统命令 七、文件内容查看命令 一、Linux资源管理方式 linux操作系统采用一个文档树来组织所有的资源。这棵树的根目录的名字叫做&#xff1a;//…

护网HW面试常问——webshell内存马流量特征以及查杀

参考&#xff1a;学习干货|HVV必学远控工具及Webshell流量合集分析(建议收藏附面试题) 蚁剑 ini_set ini_set_time ini_set_limit ini_set("display_errors","0") 部分代码明文传输&#xff0c;较好辨认 哥斯拉 1、User-Agent (弱特征) 在默认的情况…

电脑文件误删除如何恢复?Top12电脑数据恢复软件汇总合集!(图文详解)

电脑文件误删除如何恢复&#xff1f;在日常使用电脑过程中&#xff0c;我们经常会遇到意外删除文件的情况。可能是因为按错了按键、误操作了鼠标&#xff0c;或者意外格式化了存储设备。这些情况都可能导致重要的文件不小心被删除。但是不用担心&#xff0c;有许多专业的数据恢…

【stm32】新建stm32标准库函数工程

新建stm32标准库函数工程 一.工程必要文件创建二、新建main函数三、添加库函数文件四、补充User文件夹下的文件五、工程启动文件选择 官方提供的stm32标准外设库文件所包含的内容介绍&#xff1a; 一.工程必要文件创建 前提&#xff1a;先通过keil新建一个项目工程 1.在新建工程…