• 20210902模拟赛解题报告


    评价

    这次的题目好像没有什么好喷的,还是挺不错的。

    那这次我们喷什么?喷键盘!

    一场模拟赛我换了三个键盘,其中两个是好似板砖,另一个的空格就像在玩跷跷板。

    为什么有按键那么硬的键盘!!!!/fn/fn

    中间还有一次因为换键盘,电脑要重启,然后代码没了,呜呜呜。

    题目本身还行,因为评测机太慢被卡掉 40 分,申诉之后调大了时限跑过去了。

    后来发现洛谷评测机能 1s 1e9!又能多拿 40 分!

    这是非常棒的。

    T1 是找规律题,因为细节特判被卡了一个点,这是不好的。(还好不是多组数据

    T2 写了一个枚举右端点加二分套线段树的 (O(nlog^2 n)) 做法,期望 (80),被卡 (40),后来要回来了。

    T3 只会一个 (O(n^3)) 加一个部分分特判做法,期望 (30),洛谷评测机跑的快,能拿到 (70)

    期望得分:(100+80+30=210pts)
    实际得分:(90+40+30=160pts)
    放大时限后得分:(90+80+30=200pts)
    洛谷评测:(90+80+70=240pts)

    补题通道:

    T1 T2 T3
    ( ext{U177562 lock}) ( ext{U177563 sequence}) ( ext{U177564 fight})

    没有题解,没仔细研究std,所以只讲考场做法,不是正解!!
    代码只有 T1 是自己写的(我感觉我写的比 std好看),其他的是 std。
    代码为啥使用了 Tab 字符啊,八空格有点恶心。

    T1

    找规律。

    对于 (L),不管它是奇数还是偶数,都能通过倒两次水使它们的总和达到 (L+2)

    • 偶数:先往一个杯里倒 (frac{L}{2}+0.5) 滴水,再向另一个杯里倒 (frac{L}{2}+1.5) 滴水。
    • 奇数:先往一个杯里倒 (leftlfloor frac{L}{2} ight floor +1) 滴水,再向另一个杯中到 (leftlfloor frac{L}{2} ight floor +2) 滴水。

    然后两个杯子来回倒就可以,不难发现一次向一个杯子倒两滴是最快的,直到两杯水之和达到 (R) 或者 (R-1)

    所以答案为 (2+leftlfloor frac{R-L-2}{2} ight floor)

    (R le L+2)(R le 2) 时的所有情况需要单独考虑。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<queue>
    #include<vector>
    #define LL long long
    using namespace std;
    const int MAXN = 1e5 + 10;
    const int INF = 1e9 + 7;
    const int mod = 1e9 + 7;
    
    LL L, R;
    
    LL read() {
    	LL s = 0, f = 0; char ch = getchar();
    	while(!isdigit(ch)) f = (ch == '-'), ch = getchar();
    	while(isdigit(ch)) s = (s << 3) + (s << 1) + ch - '0', ch = getchar();
    	return f ? -s : s;
    }
    
    int main() {
    //    freopen("lock.in","r",stdin);
    //    freopen("lock.out","w",stdout);
    	L = read(), R = read();
    	if(R == 1) { puts("0"); return 0; }
    	if(R <= L + 2) {
    		if(R <= 2) puts("1");
    		else puts("2");
    	} else {
    		cout << 2 + (R - L - 2) / 2 << "
    ";
    	}
    	return 0;
    }
    

    T2

    std 貌似是个双指针。

    固定右端点,二分左端点,然后用线段树求出把那一段区间赋为 (0) 最赚,对合法区间取长度最大值,时间复杂度 (O(n log^2 n))

    #include<bits/stdc++.h>
    #define ll long long
    #define pb push_back
    #define mk make_pair
    #define rint register int
    using namespace std;
    inline ll read(){ll w=1,s=0;char ch=getchar();while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}return w*s;}
    ll Sum[2000010];
    ll tmp[2000010];
    ll Max[2000010],pos[2000100];
    int A[2000010];
    ll n,p,d;
    int main()
    {
    //	freopen("sequence.in","r",stdin);
    //	freopen("sequence.out","w",stdout);
    	n=read(),p=read(),d=read();
    	for(rint i=1;i<=n;++i)
    	{
    		A[i]=read();Sum[i]=Sum[i-1]+A[i];
    	}
    	for(rint i=1;i<=d-1;++i) tmp[i]=Sum[i];
    	for(rint i=d;i<=n;++i)
    	{
    		tmp[i]=Sum[i]-Sum[i-d];
    	}
    //	if(n<=d)
    //	{
    //		cout<<n<<"
    ";
    //		return 0;
    //	}
    	int rp=0;int head=1,tail=0;
    	int ans=min(d,n);
    //	cout<<rp<<"
    ";
    	for(rint l=1;l<=n;++l)
    	{
    		while(head<=tail&&pos[head]<l+d-1) head++;
    		while(rp<n)
    		{
    			if(rp-l+1<d)
    			{
    				rp++;
    				if(rp-l+1==d)
    				{
    					while(head<=tail&&tmp[rp]>Max[tail]) tail--;
    					Max[++tail]=tmp[rp];
    					pos[tail]=rp;
    				}
    			}
    			else
    			{	ll tt=-1e18;
    				if(head<=tail) tt=max(tt,Max[head]);
    				tt=max(tt,tmp[rp+1]);
    				if(Sum[rp+1]-Sum[l-1]-tt<=p)
    				{
    					rp++;
    					while(head<=tail&&tmp[rp]>Max[tail]) tail--;
    					Max[++tail]=tmp[rp];
    					pos[tail]=rp;
    				}
    				else break;
    			}
    		}
    		ans=max(ans,rp-l+1);
    	}cout<<ans;
    	return 0;
    }
    

    T3

    std 写了个线段树????

    (k=0) 的情况答案显然为 (0)

    考虑维护一个 (f_{a,b}) 表示 (a,b)两个点同时被多少线段覆盖。

    枚举所有三元组 ((a,b,c)),显然合法情况只有两种,利用 (f) 数组判断是否合法即可。

    时间复杂度 (O(n^3))

    洛谷评测跑的快把 (n=1000) 的部分卡过去了。

    #include<bits/stdc++.h>
    #define ll long long
    #define pb push_back
    #define mk make_pair
    #define rint register int
    //#define int ll
    using namespace std;
    inline int read(){int w=1,s=0;char ch=getchar();while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}return w*s;}
    typedef pair<ll,ll> pa;
    vector<pa> vec[200010];
    int n,m;ll A[500010];
    ll tot=0,q[500010];
    ll Sum[500010],tag[500010],du[500100];
    inline void pushdown(int now,int l,int r)
    {
    	if(tag[now])
    	{	int mid=(l+r)>>1;
    		tag[now<<1]^=1;
    		tag[now<<1|1]^=1;
    		Sum[now<<1]=(mid-l+1)-Sum[now<<1];
    		Sum[now<<1|1]=(r-mid)-Sum[now<<1|1];
    		tag[now]=0;
    	}
    }
    inline void Modify(int now,int l,int r,int x,int y)
    {
    //	cout<<now<<" "<<l<<" "<<r<<" "<<x<<" "<<y<<'
    ';
    	if(x<=l&&r<=y)
    	{
    		Sum[now]=(r-l+1)-Sum[now];
    	//	cout<<Sum[now]<<"
    ";
    		tag[now]^=1;
    		return ;
    	}pushdown(now,l,r);
    	int mid=(l+r)>>1;
    	if(x<=mid) Modify(now<<1,l,mid,x,y);
    	if(y>mid) Modify(now<<1|1,mid+1,r,x,y);
    	Sum[now]=Sum[now<<1]+Sum[now<<1|1];
    }
    inline ll Query(int now,int l,int r,int x,int y)
    {	if(x>y) return 0;
    	if(x<=l&&r<=y)
    	{
    		return Sum[now];
    	}pushdown(now,l,r);
    	int mid=(l+r)>>1;
    	ll res=0;
    	if(x<=mid) res=Query(now<<1,l,mid,x,y);
    	if(y>mid) res+=Query(now<<1|1,mid+1,r,x,y);
    	Sum[now]=Sum[now<<1]+Sum[now<<1|1];
    	return res;
    }
    inline void Solve()
    {
    	for(rint i=1;i<=n;++i)
    	{
    		if(i!=1)
    		{
    			Modify(1,1,n,i-1,i-1);
    		}
    		int sz=vec[i].size();
    		for(rint j=0;j<sz;++j)
    		{
    			pa tmp=vec[i][j];
    			int l=tmp.first,r=tmp.second;
    			Modify(1,1,n,l,r);
    		}
    		du[i]=Query(1,1,n,1,i-1)+Query(1,1,n,i+1,n);
    	//	cout<<du[i]<<"
    ";
    	}ll ans=1ll*n*(n-1)*(n-2)/6;
    	for(rint i=1;i<=n;++i)
    	{
    		ans-=1ll*(du[i]*(du[i]-1))/2;
    	}cout<<ans;
    }
    int main()
    {
    //	freopen("fight.in","r",stdin);
    //	freopen("fight.out","w",stdout);
    	n=read();m=read();
    	for(rint i=1;i<=n;++i)
    	{
    		A[i]=read();
    		q[++tot]=A[i];
    	}sort(A+1,A+tot+1);
    	for(rint i=1;i<=m;++i)
    	{
    		int x=read(),y=read();
    		x=lower_bound(A+1,A+tot+1,x)-A;
    		y=upper_bound(A+1,A+tot+1,y)-A-1;
    	//	cout<<x<<" "<<y<<"
    ";
    		if(x>=y) continue;
    		vec[x].pb(mk(x,y));
    		vec[y+1].pb(mk(x,y));
    	}
    	Solve();
    	return 0;
    }
    
  • 相关阅读:
    A Node Influence Based Label Propagation Algorithm for Community detection in networks 文章算法实现的疑问
    Fast Newman-FN算法以及模块度定义介绍
    Label Propagation Algorithm LPA 标签传播算法解析及matlab代码实现
    设计一个smartnic
    Intel GEN11 GPU
    Intel GEN9 GPU
    Shared Virtual Memory (SVM) Functions
    connect via ssh to virtualbox guest vm without knowing ip address
    smartnic
    技术精品翻译
  • 原文地址:https://www.cnblogs.com/Silymtics/p/15223511.html
Copyright © 2020-2023  润新知