10.15 模拟赛
又是AK失败的一天
T1 小M的算式
题目大意:
一个数字组成的字符串 每两个字符间可以加入+或=或不加入符号(整个串只能加入一个=)
求这个字符串能否变成一个等式
思路:
爆搜 枚举一下等号出现位置
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #include<map> 10 #define inf 2139062143 11 #define ll long long 12 #define MAXN 100100 13 using namespace std; 14 inline int read() 15 { 16 int x=0,f=1;char ch=getchar(); 17 while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();} 18 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 19 return x*f; 20 } 21 int n,m,i,ok; 22 ll a[2],t,f; 23 char s[50],tmp[50]; 24 inline void work() 25 { 26 for(i=1,f=t=a[0]=a[1]=0;i<=m;i++) 27 { 28 if(isdigit(tmp[i])) t=t*10+tmp[i]-'0'; 29 else if(tmp[i]=='+') a[f]+=t,t=0; 30 else a[f]+=t,f^=1,t=0; 31 } 32 a[f]+=t; 33 if(a[0]==a[1]) ok=1; 34 } 35 void dfs(int x,int mdf) 36 { 37 if(x==n) {if(mdf) work();return ;} 38 tmp[++m]=s[x]; 39 dfs(x+1,mdf);if(ok==1) return ; 40 tmp[++m]='+';dfs(x+1,mdf);if(ok==1) return ;m--; 41 if(!mdf) {tmp[++m]='=';dfs(x+1,1);if(ok==1) return ;m--;} 42 m--; 43 } 44 int main() 45 { 46 freopen("equation.in","r",stdin); 47 freopen("equation.out","w",stdout); 48 int T=read(); 49 while(T--) 50 { 51 scanf("%s",s);n=strlen(s),m=0; 52 ok=0;dfs(0,0); 53 puts(ok?"Yes":"No"); 54 } 55 }
T2 小R的调度
题目大意:
一个长度为 n 的 01 序列 A,每次可以交换当前 A[i]与 A[j] 的值,并需要付出 c[i] + c[j]的代价
在若干次交换后,得分为最终 A 序列的逆序对数减去交换中付出的代价之和 求最大得分
思路:
可以发现交换对答案的贡献仅为与这个区间的长度与两端的代价有关
考虑贪心 贪到不能贪为止
(管老师代码)(并没有想到这种贪心)
1 #include<bits/stdc++.h> 2 #define INF 2147483647 3 #define LL long long 4 #define ULL unsigned long long 5 #define MAXN 100+2500 6 #define rep(i,s,t) for(int i=s;i<=t;++i) 7 #define dwn(i,s,t) for(int i=s;i>=t;--i) 8 9 using namespace std; 10 inline int read(){ 11 int x=0; bool f=true; char ch=getchar(); 12 for(;!isdigit(ch);ch=getchar())if(ch=='-')f=false; 13 for(;isdigit(ch);ch=getchar())x=ch-'0'+(x<<3)+(x<<1); 14 return f==true?x:-x; 15 } 16 17 inline void write(int x){ 18 ULL t=10,len=1; while(t<=x)t*=10,len++; 19 while(len--)t/=10,putchar(x/t+48),x%=t; 20 return ; 21 } 22 23 int n,c[MAXN],a[MAXN]; char str[MAXN]; 24 void init(){ 25 n=read(); scanf("%s",str+1); 26 rep(i,1,n)c[i]=read(),a[i]=str[i]-'0'; 27 return ; 28 } 29 30 int ans=0; 31 void work(){ 32 int now=0; 33 rep(i,1,n){ 34 if(a[i]==0)ans+=now; 35 else now++; 36 } 37 while(1){ 38 int s=0,L=0,R=0,num=0; 39 rep(i,1,n){ 40 if(a[i]==1){ 41 if(!s)continue; 42 if(i-c[i]-s-c[s]>num) 43 num=i-c[i]-s-c[s],L=s,R=i; 44 } 45 else if(-i-c[i]>=-s-c[s]||!s)s=i; 46 } 47 if(num<0||L+R==0)break; 48 cout<<L<<" "<<R<<" "<<num<<endl; 49 ans+=num,swap(a[L],a[R]); 50 } 51 write(ans); 52 return ; 53 } 54 55 int main(){ 56 freopen("inverse5.in","r",stdin); 57 freopen("inverse.out","w",stdout); 58 init(); work(); return 0; 59 }
T3 小C的机器人
题目大意:
一些机器人在一棵树上的节点上 树的节点可以为黑色或白色
支持三种操作:
1 把编号从l-r的机器人移动到x节点
2 把编号为l-r的机器人向根节点走k步(如果走到根节点就不动)
3 查询编号为x的机器人所在的节点到其字数内所有黑点的距离之和 并把这个节点变色
思路:
对于1 2 操作可以时候可以使用线段树维护 方式与区间赋值和区间加法几乎一样
对于3操作可以使用dfs序+两个树状数组
两个树状数组分别维护字数内黑点的个数与所有黑点到根的距离之和 加加减减即可
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #include<map> 10 #define inf 2139062143 11 #define ll long long 12 #define MAXN 200100 13 using namespace std; 14 inline int read() 15 { 16 int x=0,f=1;char ch=getchar(); 17 while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();} 18 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 19 return x*f; 20 } 21 int n,m,f[MAXN][19],l[MAXN],r[MAXN],dep[MAXN]; 22 int fst[MAXN],nxt[MAXN<<1],to[MAXN<<1],cnt; 23 int tag[MAXN<<2],tagp[MAXN<<2],val[MAXN]; 24 inline void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;} 25 void dfs(int x) 26 { 27 l[x]=++cnt; 28 for(int i=1;(1<<i)<=dep[x];i++) f[x][i]=f[f[x][i-1]][i-1]; 29 for(int i=fst[x];i;i=nxt[i]) 30 if(to[i]!=f[x][0]) {f[to[i]][0]=x,dep[to[i]]=dep[x]+1;dfs(to[i]);} 31 r[x]=cnt; 32 } 33 inline int anc(int x,int t) 34 { 35 if(t>dep[x]) return 1; 36 for(int i=18;i>=0;i--) 37 if((1<<i)&t) x=f[x][i]; 38 return x; 39 } 40 struct fenwick_tree 41 { 42 ll c[MAXN]; 43 inline int lowbit(int x) {return x&(-x);} 44 inline void mdf(int x,int w) {for(;x<=n;x+=lowbit(x)) c[x]+=w;} 45 inline ll ask(int x) {if(!x) return 0LL;ll res=0;for(;x;x-=lowbit(x)) res+=c[x];return res;} 46 }c1,c2; 47 inline void pshd(int k) 48 { 49 if(tag[k]) tag[k<<1]=tag[k<<1|1]=tag[k],tagp[k<<1]=tagp[k<<1|1]=tagp[k]; 50 else if(tagp[k]) tagp[k<<1]+=tagp[k],tagp[k<<1|1]+=tagp[k]; 51 tag[k]=tagp[k]=0; 52 } 53 void mdfp(int k,int l,int r,int a,int b,int x) 54 { 55 if(l==a&&b==r) {tagp[k]+=x;return ;} 56 int mid=l+r>>1;pshd(k); 57 if(b<=mid) mdfp(k<<1,l,mid,a,b,x); 58 else if(a>mid) mdfp(k<<1|1,mid+1,r,a,b,x); 59 else {mdfp(k<<1,l,mid,a,mid,x);mdfp(k<<1|1,mid+1,r,mid+1,b,x);} 60 } 61 void mdf(int k,int l,int r,int a,int b,int x) 62 { 63 if(l==a&&b==r) {tag[k]=x,tagp[k]=0;return ;} 64 int mid=l+r>>1;pshd(k); 65 if(b<=mid) mdf(k<<1,l,mid,a,b,x); 66 else if(a>mid) mdf(k<<1|1,mid+1,r,a,b,x); 67 else {mdf(k<<1,l,mid,a,mid,x);mdf(k<<1|1,mid+1,r,mid+1,b,x);} 68 } 69 int query(int k,int l,int r,int x) 70 { 71 if(l==r) return anc(tag[k],tagp[k]); 72 int mid=l+r>>1;pshd(k); 73 if(x<=mid) return query(k<<1,l,mid,x); 74 else return query(k<<1|1,mid+1,r,x); 75 } 76 int main() 77 { 78 freopen("robot.in","r",stdin); 79 freopen("robot.out","w",stdout); 80 n=read(),m=read();int a,b,c,q;ll res=0; 81 for(int i=1;i<n;i++) {a=read(),b=read();add(a,b);add(b,a);val[a]=val[b]=1;} 82 for(int i=1;i<=m;i++) mdf(1,1,m,i,i,read()); 83 cnt=0;dfs(1);q=read(); 84 while(q--) 85 { 86 c=read(),res=0; 87 if(c==1) {a=read(),b=read(),c=read();mdf(1,1,m,a,b,c);} 88 else if(c==2) {a=read(),b=read(),c=read();mdfp(1,1,m,a,b,c);} 89 else 90 { 91 a=read(),a=query(1,1,m,a); 92 res=c2.ask(r[a])-c2.ask(l[a]-1)-(c1.ask(r[a])-c1.ask(l[a]-1))*dep[a]; 93 c2.mdf(l[a],val[a]*dep[a]);c1.mdf(l[a],val[a]);val[a]=-val[a]; 94 printf("%lld\n",res); 95 } 96 } 97 }