ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2022南外集训 Day3

2022-07-06 20:00:21  阅读:136  来源: 互联网

标签:int Day3 long 南外 while read 2022 include id


杂言

改题,码力还得练

T1

枚举 不放码了

T2 奶牛的问候

写的时候不知道咋就70pts了,真心写不明白简单的模拟

T2 70pts
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<string> 
#include<cstdlib>
#include<set>
#include<bitset>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn=1e5+5;
inline int read()
{
    int x=0,y=1; char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') y=-1; c=getchar();}
    while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    return x*y;
}
int n,m;
char s[10];
int a[maxn],b[maxn];
int ta[maxn],tb[maxn];
int main()
{
    srand(time(0));
    n=read(); m=read();
    for(int i=1;i<=n;i++)
    {
        int t=read(); scanf("%s",s+1);
        if(s[1]=='L') a[i]=a[i-1]-t;
        else a[i]=a[i-1]+t;
        ta[i]=ta[i-1]+t;
    }
    for(int i=1;i<=m;i++)
    {
        int t=read(); scanf("%s",s+1);
        if(s[1]=='L') b[i]=b[i-1]-t;
        else b[i]=b[i-1]+t;
        tb[i]=tb[i-1]+t;
    }
    if(n<m) {swap(a,b); swap(ta,tb); swap(n,m);}
    int ans(0);
    for(int i=2;i<=n;i++)
    {
        int pos=upper_bound(tb+1,tb+1+m,ta[i])-tb-1;
        int u=b[pos]+ta[i]-tb[pos];
        if(pos==m) u=b[pos];
        int pre=(u==b[pos])?b[pos-1]:b[pos];
        if((a[i-1]>u&&a[i]<u)||(a[i-1]<u&&a[i]>u)) ans++;
    }
    printf("%d\n",ans);
    return 0;
}
/*1 4
3 L
4 L
1 R
2 L
5 R*/

粘一个A掉的码
应该是按照时间\(t\)模拟

T2 accept
#include<bits/stdc++.h>
using namespace std;
int n,m;
long B=0,E=0;
int ans,cnt1=1,cnt2=1;
int t=0;
bool flag=0;
struct mdy{
    int x;
    char c;
}a[50005],b[50005];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d %c",&a[i].x,&a[i].c);
        a[i].x+=a[i-1].x; 
    }
    for(int i=1;i<=m;i++){
        scanf("%d %c",&b[i].x,&b[i].c);
        b[i].x+=b[i-1].x;
    }
    while(cnt1<=n||cnt2<=m){
        t++;
        if(a[cnt1].c=='L') B--;
        else if(a[cnt1].c=='R') B++;
        if(b[cnt2].c=='L') E--;
        else if(b[cnt2].c=='R') E++;
        if(B==E&&flag) flag=0,ans++;
        else if(B!=E) flag=1;
        if(t==a[cnt1].x) cnt1++;
        if(t==b[cnt2].x) cnt2++;
    }
    printf("%d",ans);
    return 0;
}

T3 监视奶牛

考场上95,推出了一个hack,但是真不想写了
放个95pts

T3 95pts
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<string> 
#include<cstdlib>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn=1e5+5;
inline int read()
{
    int x=0,y=1; char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') y=-1; c=getchar();}
    while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    return x*y;
}
struct node
{
    int x,y;
    bool operator <(const node &a) const
    {return x<a.x;} 
}vec[maxn],t[5];
int n,cnt(0),tot(0);
int nxt[maxn],pre(0);
int len[maxn];
int main()
{
    map<int,int>mX;
    scanf("%d",&n);
    int xcnt=0,ycnt=0,x,y;
    for(int i=1;i<=n;i++){
        scanf("%d %d",&x,&y);
        if(!mX[x])mX[x]=++xcnt;
        if(!mX[y])mX[y]=++xcnt;
        x=mX[x],y=mX[y];
        vec[i]=(node){x,y};
    }
    sort(vec+1,vec+1+n);
    /*for(int i=1;i<=n;i++)
      cout<<vec[i].x<<" "<<vec[i].y<<endl;
      cout<<"------\n";*/
    for(int i=1;i<=n;i++) nxt[i]=i;
    for(int i=1;i<=n;i++)
        if(vec[i].x^vec[i-1].x) nxt[pre]=i-1,pre=i;
    for(int i=1;i<=n;i=nxt[i]+1)
    {
        if(cnt>3) {printf("%d\n",0); return 0;}
        for(int j=i;j<=nxt[i];j++)
        {
            bool flag=0;
            for(int k=1;k<=cnt;k++)
                if(t[k].x==vec[j].x||t[k].y==vec[j].y) {flag=1; break;}
            for(int k=1;k<=cnt;k++)
            	if(t[k].x!=vec[j].x&&t[k].y==vec[j].y&&len[k]>1) flag=0;
            if(flag) continue;
            else
			{
				t[++cnt]=vec[j];
				len[cnt]=nxt[i]-i+1;
				break;
			}
        }
    }
    if(cnt<=3||n<=3) printf("%d\n",1);
    else printf("%d\n",0);
    return 0;
}

再放个满分,感觉就暴力dfs检查就行

T3 accept
#include<bits/stdc++.h>
using namespace std;
int n,l=0;
struct node{
    int x,y;
}a[50010];
node c[4];
int solve(int i){
    if(i>n) return 1;
    int f=0;
    for(int j=1;j<=l;j++)if(c[j].x==a[i].x||c[j].y==a[i].y)f=1;
    if(f) return solve(i+1);
    if(l==3) return 0;
    int p=0;
    l++;
    c[l]=(node){a[i].x,-1}; p=p||solve(i+1);
    c[l]=(node){-1,a[i].y}; p=p||solve(i+1); 
    l--;
    return p;
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i].x>>a[i].y;
    cout<<solve(1);
    return 0;
}

T4 黑白棋

简单基础的线段树区间翻转操作(1A

T4 accept
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<string> 
#include<cstdlib>
#include<map>
#include<bitset>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn=1e5+5;
#define lc(x) x<<1
#define rc(x) x<<1|1
#define sum(x) tree[x].sum
#define tag(x) tree[x].tag
inline int read()
{
	int x=0,y=1; char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') y=-1; c=getchar();}
	while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
	return x*y;
}
int n,m;
struct segtree
{
	int tag,sum;
}tree[maxn<<2];
void push_up(int id)
{
	sum(id)=sum(lc(id))+sum(rc(id));
	return ; 
}
void push_down(int id,int l,int r)
{
	if(!tag(id)) return ;
	int mid=(l+r)>>1;
	sum(lc(id))=(mid-l+1)-sum(lc(id));
	sum(rc(id))=(r-mid)-sum(rc(id));
	tag(lc(id))^=1; tag(rc(id))^=1;
	tag(id)=0;
	return ;
}
void modify(int id,int l,int r,int x,int y)
{
	if(x<=l&&r<=y)
	{
		sum(id)=(r-l+1)-sum(id);
		tag(id)^=1;
		return ;
	}
	push_down(id,l,r);
	int mid=(l+r)>>1;
	if(x<=mid) modify(lc(id),l,mid,x,y);
	if(y>mid) modify(rc(id),mid+1,r,x,y);
	push_up(id);
	return ;
}
int query(int id,int l,int r,int x,int y)
{
	if(x<=l&&r<=y) return sum(id);
	push_down(id,l,r);
	int mid=(l+r)>>1,tot(0);
	if(x<=mid) tot+=query(lc(id),l,mid,x,y);
	if(y>mid) tot+=query(rc(id),mid+1,r,x,y);
	return tot;
}
int main()
{
	n=read(); m=read();
	while(m--)
	{
		int opt,l,r;
		opt=read();
		l=read(); r=read();
		if(opt) printf("%d\n",query(1,1,n,l,r));
		else modify(1,1,n,l,r);
	}
	return 0;
}

T5 字符串分割

就是给个括号序列,要求分成两个子集,每个子集括号保证匹配,求方案总数
简单小dp,考场上没推完
考虑一件事,括号匹配可以将 \((\) 看作\(1\),\()\) 看作 \(-1\),然后只要保证序列在任何位置都有前缀和 \(sum[i]>=0\)
那么考虑\(dp[i][j][k]\)代表前i个字符,当前第一个子集前缀和是j,第二个子集前缀和是k的方案总数
然后考虑转移,只要讨论当前\(i\)字符给哪边就行
再考虑一个性质,因为a+b就是s串,因此知道了当前a子集的前缀和,由整体前缀和可以推出b子集的前缀和,这样转移只需要两维
\(dp[i][j]+=dp[i-1][j]+dp[i-1][j-val[i]]\)

T5 accept
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<string> 
#include<cstdlib>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn=1e3+5;
const int mod=2012;
inline int read()
{
    int x=0,y=1; char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') y=-1; c=getchar();}
    while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    return x*y;
}
char s[maxn];
int dp[maxn][maxn],n;
int sum[maxn];
int mx,tot(0);
int main()
{
	scanf("%s",s+1);
	n=strlen(s+1);
	for(int i=1;i<=n;i++)
	{
		if(s[i]=='(') sum[i]=sum[i-1]+1;
		else sum[i]=sum[i-1]-1;
		mx=max(mx,sum[i]);
	}
	dp[0][0]=1;
	for(int i=1;i<=n;i++)
	{
		for(int j=0;j<=mx;j++)
		{
			if(sum[i]-j<0) continue;
			int t=(s[i]=='(')?1:-1;
			dp[i][j]=((dp[i-1][j]+dp[i][j])%mod+dp[i-1][j-t])%mod;
		}
	}
	printf("%d\n",dp[n][0]%mod);
	return 0;
}

T6 Chase Death

题意:首先给你\(n\)个位置从\(1\)开始,告诉你如果走到\(n\)位置外,即\(pos>n\)时会死
给出n个数,每个位置\(i\)上面的数代表它可以走到\(i+a[i]\),可以理解为跳\(a[i]\)格
给出\(m\)个操作,有修改和询问,询问是询问在位置\(i\)走几步可以死掉,修改是修改\(i\)位置的\(a[i]\),改成一个数

这道题思维是真的妙(
我们首先考虑,跳格子这玩意维护很难,而且每次修改会修改从头开始能走到\(i\)的一长串点,那就考虑大力分块(感觉思维还是不顺
我们分块处理一点,把每个块中的位置\(i\)找到它能 跳出这个块 ,可能进入下一个块,或者跳了很远的结束位置位置,并顺带求出需要几步
举个例子: block=3
pos:1 2 3 4 5
a[i]: 2 1 2 3 1
nxt: 5 5 5 - -
stp: 2 2 1 - -
简单结束一下,块长是3,从1开始,我们需要走 1->3->5 才能走到别的块
步数是两步,位置2也同理,2->3->5,走两步
这样我们\(O(n \sqrt n)\)处理出了一个块内的位置可以跳”一大步“走到的位置
(保证至少是下一个块)
这样随便在某个块某个位置里开始跳,最坏情况一次会跳至少\(\sqrt n\)步,保证while循环次数少于\(\sqrt n\)
这样一次询问就是\(O(\sqrt n)\)的
考虑修改怎么保证复杂度和正确性,我们找到修改位置所在块,因为这个位置的改变,会导致这个位置 前面的 同样在块里的 位置的\(nxt\)和\(stp\)的改变
因此,只要暴力\(O(\sqrt n)\) 重算一下这个块里面的信息就可以了

T6 accept
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<string> 
#include<cstdlib>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn=2e5+5;
inline int read()
{
    int x=0,y=1; char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') y=-1; c=getchar();}
    while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    return x*y;
}
int n,m,block;
int nxt[maxn],bel[maxn*2];
int st[maxn],top[maxn];
int main()
{
	n=read();
	for(int i=1;i<=n;i++) nxt[i]=read();
	block=(int)sqrt(n);
	for(int i=1;i<=n;i++)
		bel[i]=(i-1)/block+1;
	m=read();
	for(int i=n;i>=1;i--)
	{
		if(bel[i]==bel[i+nxt[i]])
			st[i]=st[i+nxt[i]]+1,top[i]=top[i+nxt[i]];
		else st[i]=1,top[i]=i+nxt[i];
	}
	while(m--)
	{
		int opt,x,y;
		opt=read();
		if(opt==1)
		{
			x=read(); int u=x+1,ans(0);
			while(u<=n) 
			{ans+=st[u]; u=top[u];}
			printf("%d\n",ans);
		}
		else 
		{
			x=read()+1; y=read();
			nxt[x]=y;
			for(int i=min(bel[x]*block,n);i>=(bel[x]-1)*block;i--)
			{
				if(bel[i+nxt[i]]==bel[i])
					st[i]=st[i+nxt[i]]+1,top[i]=top[i+nxt[i]];
				else st[i]=1,top[i]=i+nxt[i];
			}
		}
	}
	return 0;
}

标签:int,Day3,long,南外,while,read,2022,include,id
来源: https://www.cnblogs.com/mastey/p/16452305.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有