@ivorysi
2017-11-10T10:57:53.000000Z
字数 38177
阅读 774
复习
字符串的操作也有一些说道吧……毕竟……总忘
C类型的字符串,即char数组
从1开始存会更加方便
一定要#include!这是一个很有用的头文件!memset也在里面
char s[10000];
scanf("%s",s+1);
如果读含有空格的字符串呢……我们可以选择getchar一个个扫进来,还有一个(在字符串空间足够的情况下)gets可以解决这个问题
char s[1005];
int main() {
gets(s+1);
printf("%s\n",s+1);
}
strlen(char *s);
char *s="RANK 1";
int main() {
printf("%d\n",strlen(s));
}
输出
6
strcpy(char *destin,char *source) 将第二个字符复制到第一个字符串
strncpy(char *destin,char *source,int n) 将第二个字符串的前n个字符复制给第一个
char to[1005],*from="sigongzi is green sun";
int main() {
strncpy(to+1,from,8);
printf("%s\n",to+1);
strcpy(to+1,from);
printf("%s\n",to+1);
}
输出:
sigongzi
sigongzi is green sun
strcmp(char *s1,char *s2)
返回值为0时两字符串相等,否则返回第一个不相同的位置ASCII码的差值
char *s1="sigongzi",*s2="zigongsi",*s3="sigongzi";
int main() {
printf("%d\n",strcmp(s1,s2));
printf("%d\n",strcmp(s2,s1));
printf("%d\n",strcmp(s1,s3));
}
输出
-7
7
0
有两个个很妙的操作叫sprintf和sscanf
char *s1="4711";
int x;
int main() {
sscanf(s1,"%d",&x);
printf("%d\n",x);
}
char s[1005];
int x=4711;
int main() {
sprintf(s,"%d",x);
printf("%s\n",s);
}
这两个的输出都是
4711
这也是一个很方便的类型
它的链接操作可以直接用+完成
比较可以用>、<、==
两个字符串之间的赋值可以用s1=s2完成
获得长度可以用s.length()
询问某个字符可以直接用数组的方式s[i]询问
s.insert(pos,s2)
是在pos前面插入s2这个串
s.substr(pos,n)
返回下标pos起长度为n的子串
s.erase(pos,n)
删除pos起的n个字符
s.replace(pos,n,s2)
将pos起n个字符替换成s2的内容
s.find(s2,pos)
查找pos起s2第一次出现的位置
返回一个c语言风格的指针,即char*
memset……这个太熟了
memcpy(dest,source,n);
int a[4]={4,7,1,1};
int b[4];
int main() {
memcpy(b,a,sizeof(a));
siji(i,0,3) {
printf("%d ",b[i]);
}
}
输出
4711
front() 队首元素
pop() 弹出
push() 放进去
empty() 是否为空
push() 放进去
pop() 弹出来
top() 栈顶元素
empty() 是否为空
查找元素是否被建立过是
count()
插入可以像数组一样插入,询问可以像数组一样询问
注意multiset删除的时候删除某个特定元素需要用迭代器
find()查找
erase()删除
insert()插入
一个begin()指针是真实存在的,另一个end()作为结束标记是悬空的,不能访问
一般就是push_back()和pop_back()
int a[11]={1,2,3,4,5,6,7,7,7,7,8};
int main() {
int pos1=lower_bound(a,a+11,7)-a;
int pos2=upper_bound(a,a+11,7)-a;
printf("%d %d\n",pos1,pos2);
}
输出
6 10
也就是说lower_bound是大于等于某个数的第一个
upper_bound是大于某个数的第一个
这大概应该是从入门就接触的第一个算法,也是将旷日持久陪伴我们的算法……这个算法的原理在小学就学过了……可惜细节太多了,唯一的办法就是多写了,鉴于noip考的算法不可能考裸的高精,一般的dp只涉及乘法和加法……那么板子先放在这里了
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
//#define ivorysi
using namespace std;
typedef long long ll;
const int BASE=100000000;
const int WIDTH=8;
struct bignum {
vector<int> v;
bignum operator = (long long num) {
v.clear();
do{
v.push_back(num%BASE);
num/=BASE;
}while(num>0);
return *this;
}
bignum operator = (const string &str) {
v.clear();
int len=(str.length()-1)/WIDTH+1,x;
xiaosiji(i,0,len) {
int end=str.length()-i*WIDTH;
int st=max(0,end-WIDTH);
sscanf(str.substr(st,end-st).c_str(),"%d",&x);
v.push_back(x);
}
return *this;
}
bignum operator + (const bignum &b) {
int lena=v.size(),lenb=b.v.size();
bignum c;
c.v.clear();
int p=0,g=0,x;
while(1) {
x=g;
if(p<lena) x+=v[p];
if(p<lenb) x+=b.v[p];
if(p>=lena && p>=lenb && x==0) {break;}
c.v.push_back(x%BASE);
g=x/BASE;
++p;
}
return c;
}
bignum operator *(const bignum &b) {
int lena=v.size(),lenb=b.v.size();
bignum c;
c.v.clear();
siji(i,0,lena+lenb) c.v.push_back(0);
xiaosiji(i,0,lena) {
ll g=0;
xiaosiji(j,0,lenb) {
ll x=(ll)v[i]*b.v[j]+g+c.v[i+j];
c.v[i+j]=x%BASE;
g=x/BASE;
}
int t=i+lenb;
while(g) {
ll x=g+c.v[t];
c.v[t]=x%BASE;
g=x/BASE;
++t;
}
}
int s=c.v.size();
gongzi(i,s-1,1) {
if(c.v[i]==0) {c.v.pop_back();}
else break;
}
return c;
}
void out() {
int s=v.size()-1;
printf("%d",v[s]);
--s;
gongzi(i,s,0) {
printf("%08d",v[i]);
}
putchar('\n');
}
}a,b;
string stra,strb;
int main() {
cin>>stra>>strb;
a=stra;b=strb;
bignum t=a*b;
t.out();
}
这个名字看的我很眼熟,但我的确是很久没写了
noip2013火柴排队
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define pii pair<int,int>
#define fi first
#define se second
#define mod 99999997
//#define ivorysi
using namespace std;
typedef long long ll;
int read() {
int res=0;
char c=getchar();
while(c<'0' || c>'9') c=getchar();
while(c>='0' && c<='9') {
res=res*10-'0'+c;
c=getchar();
}
return res;
}
pii a[1000005],b[1000005];
int n;
int c[1000005],num[1000005];
ll ans;
void merge(int l,int m,int r) {
int pa=l,pb=m+1,p=l;
while(pa<=m && pb<=r) {
if(c[pa]<c[pb]) {
num[p++]=c[pa++];
}
else {
num[p++]=c[pb++];
ans+=(m-pa+1);
ans%=mod;
}
}
while(pa<=m) {num[p++]=c[pa++];}
while(pb<=r) {num[p++]=c[pb++];}
siji(i,l,r) c[i]=num[i];
}
void mergesort(int l,int r) {
if(l<r) {
int m=(l+r)>>1;
mergesort(l,m);
mergesort(m+1,r);
merge(l,m,r);
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
n=read();
siji(i,1,n) {
a[i].fi=read();
a[i].se=i;
}
siji(i,1,n) {
b[i].fi=read();
b[i].se=i;
}
sort(a+1,a+n+1);
sort(b+1,b+n+1);
siji(i,1,n) {
c[a[i].se]=b[i].se;
}
mergesort(1,n);
printf("%lld\n",ans);
}
虽然应该归类到数据结构,但是都是求逆序对,就放一起了
noip2013火柴排队
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define pii pair<int,int>
#define fi first
#define se second
#define mod 99999997
//#define ivorysi
using namespace std;
typedef long long ll;
int read() {
int res=0;
char c=getchar();
while(c<'0' || c>'9') c=getchar();
while(c>='0' && c<='9') {
res=res*10-'0'+c;
c=getchar();
}
return res;
}
pii a[1000005],b[1000005];
int n;
int c[1000005];
ll ans;
int tr[1000005];
int lowbit(int x){return x&(-x);}
void change(int pos) {
while(pos<=n) {
++tr[pos];
pos+=lowbit(pos);
}
}
int query(int pos) {
int res=0;
while(pos>0) {
res+=tr[pos];
pos-=lowbit(pos);
}
return res;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
n=read();
siji(i,1,n) {
a[i].fi=read();
a[i].se=i;
}
siji(i,1,n) {
b[i].fi=read();
b[i].se=i;
}
sort(a+1,a+n+1);
sort(b+1,b+n+1);
siji(i,1,n) {
c[a[i].se]=b[i].se;
}
siji(i,1,n) {
ans+=query(n)-query(c[i]-1);
change(c[i]);
ans%=mod;
}
printf("%lld\n",ans);
}
导弹拦截
我似乎已经很久没写过这个东西了
lower_bound 和upper_bound 真好用
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
//#define ivorysi
using namespace std;
typedef long long ll;
int n;
int a[100005];
int f[100005],cnt;
void solve() {
while(~scanf("%d",&a[++n]));
--n;
gongzi(i,n,1) {
if(a[i]>=f[cnt]) {
f[++cnt]=a[i];
}
else {
int x=upper_bound(f,f+cnt,a[i])-f;
if(a[i]<f[x]) f[x]=a[i];
}
}
printf("%d\n",cnt);
cnt=0;
siji(i,1,n) {
if(a[i]>f[cnt]) {
f[++cnt]=a[i];
}
else {
int x=lower_bound(f,f+cnt,a[i])-f;
if(a[i]<f[x]) f[x]=a[i];
}
}
printf("%d\n",cnt);
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
}
ax+by=g的几个解
基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题
给出N个固定集合{1,N},{2,N-1},{3,N-2},...,{N-1,2},{N,1}.求出有多少个集合满足:第一个元素是A的倍数且第二个元素是B的倍数。
提示:
对于第二组测试数据,集合分别是:{1,10},{2,9},{3,8},{4,7},{5,6},{6,5},{7,4},{8,3},{9,2},{10,1}.满足条件的是第2个和第8个。
第1行:1个整数T(1<=T<=50000),表示有多少组测试数据。
第2 - T+1行:每行三个整数N,A,B(1<=N,A,B<=2147483647)
对于每组测试数据输出一个数表示满足条件的集合的数量,占一行。
2
5 2 4
10 2 3
1
2
ax+by=n+1 看看n+1是不是g的倍数
如果是的话就从x的第一个解开始计算,每一个解的距离都是lcm(a,b)
如果第一个x是0的话就让x=b/g
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MAXN 100005
//#define ivorysi
using namespace std;
typedef long long ll;
ll read() {
ll res=0;
char c=getchar();
while(c < '0' || c > '9') c=getchar();
while(c>='0' && c<='9') {
res=res*10-'0'+c;
c=getchar();
}
return res;
}
int gcd(ll a,ll b) {
return b==0 ? a:gcd(b,a%b);
}
int ex_gcd(ll a,ll b,ll &x,ll &y) {
if(b==0) {
x=1;y=0;
return a;
}
else {
int res=ex_gcd(b,a%b,y,x);
y-=a/b*x;
return res;
}
}
int t;
ll n,a,b;
void solve() {
n=read();a=read();b=read();
ll x=0,y=0;
ll g=ex_gcd(a,b,x,y);
x=((x%b)+b)%b;
if((n+1)%g!=0) {
puts("0");
return;
}
else {
x=(ll)x*((n+1)/g)%(b/g);
if(x==0) x=b/g;
if((ll)x*a>n) {
puts("0");return;
}
int ans=(n-a*x)/((ll)a/g*b)+1;
printf("%d\n",ans);
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
t=read();
while(t--) {
solve();
}
}
暴力(violent)
时间:1s(如果用lemon评测,请开2s)
空间:64MB
如果认为本题正解有误或数据有误或正解不够优请通知我。
17.11.1:数据重新更新,如果仍有问题请通知我。
背景
XYC是未来OI的红太阳,今天就要参加2117 NOI professional,并打算ak全场。
但是很不幸,今年出2117 NOI professional的人是ZSW,他出了很多道大模拟题目,并伴随各种高深算法,很多学生纷纷爆零,走上了高考的不归路。
但是XYC可是未来的红太阳啊!就算题目很难,XYC神犇也不会爆零并且轻松RANK1啊,但是就算能够轻松省一,XYC还想要挑战自己的极限,得到尽可能高的分。
题面描述
本场2117 NOI professional的考试时间为TTT,共有NNN道题,当时间T<0T<0T<0时XYC就需要停止答题。
XYC初始的耐心值为WWW,当W<0W<0W<0,他就会厌倦去做这套题。
请注意做任何导致W<0W<0W<0和T<0T<0T<0的操作都是犯规的。
如果XYC下定决心要做某一道题,他就需要花费ttt的时间和www的耐心去读完题目。
当XYC读完题目后,XYC可以有三种选择且只能选择其中一种:
1. 写正解,XYC将花费tmaxtmaxtmax的时间和wmaxwmaxwmax的耐心并获得kmaxkmaxkmax的分数。
2. 写暴力,XYC有mmm种暴力可以写,每一个暴力需要花费tititi的时间和wiwiwi的耐心并获得kikiki的分数。每一道题每一种暴力只可以写一次,但XYC可以写多种暴力。
3. 写固输,XYC可以花费0的时间和0的耐心并获得1分。
请注意XYC一次只能做一件事(包括看题面,写正解,写一种暴力,写固输)。
XYC的目标是他得到的分数sumsumsum最大。
输入描述
第一行三个正整数NNN、TTT、WWW。
对于每一道题,其第一行为正整数ttt、www。
其第二行为三个正整数tmaxtmaxtmax、wmaxwmaxwmax、kmaxkmaxkmax。
其第三行为mmm。
其第四行到m+3m+3m+3行,每行三个正整数tititi、wiwiwi、kikiki。
输出描述
一行一个整数sumsumsum。
样例输入1
2 20 30
5 10
20 20 50
2
10 5 20
6 8 10
5 3
4 8 10
3
2 1 1
4 5 8
2 3 1
样例输出1
21
样例输入2
1 50 50
1 1
50 50 10000
0
样例输出2
1
数据规模
100%的数据满足,
N<=100N<=100N<=100,T<=50T<=50T<=50,W<=50W<=50W<=50,m<=40m<=40m<=40.
ki<=105ki<=10^5ki<=105,kmax<=107kmax<=10^7kmax<=107.
ttt,www,tmaxtmaxtmax,wmax<=100wmax<=100wmax<=100.
这道题很好
这道题的算法全名叫多维分组01背包……就是状态多了点,转移思路还是很简单的
适合练板子
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MAXN 100005
//#define ivorysi
using namespace std;
typedef long long ll;
int n,m,T,W;
ll vio[55][55],f[105][55][55],ans;
ll t,w,tmax,kmax,wmax;
ll tim[55],pat[55],val[55];
int read() {
int res=0;
char c=getchar();
while(c < '0' || c > '9') c=getchar();
while(c>='0' && c<='9') {
res=res*10+c-'0';
c=getchar();
}
return res;
}
void solve() {
n=read();T=read();W=read();
siji(i,1,n) {
siji(j,0,T) {
siji(l,0,W) {
f[i][j][l]=max(f[i-1][j][l],f[i][j][l]);
}
}
t=read();
w=read();
tmax=read();wmax=read();kmax=read();
gongzi(j,T,t) {
gongzi(l,W,w) {
if(j>=tmax+t && l>=wmax+w)f[i][j][l]=max(f[i-1][j-tmax-t][l-wmax-w]+kmax,f[i][j][l]);
f[i][j][l]=max(f[i-1][j-t][l-w]+1,f[i][j][l]);
}
}
memset(vio,0,sizeof(vio));
m=read();
siji(k,1,m) {
tim[k]=read();pat[k]=read();val[k]=read();
gongzi(j,T,tim[k]) {
gongzi(l,W,pat[k]) {
vio[j][l]=max(vio[j][l],vio[j-tim[k]][l-pat[k]]+val[k]);
}
}
}
siji(ti,0,T) {
siji(wi,0,W) {
gongzi(j,T,ti+t) {
gongzi(l,W,wi+w){
f[i][j][l]=max(f[i-1][j-ti-t][l-wi-w]+vio[ti][wi],f[i][j][l]);
}
}
}
}
}
siji(j,0,T) {
siji(l,0,W) {
ans=max(ans,f[n][j][l]);
}
}
printf("%lld\n",ans);
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
}
板子……
注意一下根节点的deep是1
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MAXN 500005
//#define ivorysi
using namespace std;
typedef long long ll;
int read() {
int res=0;
char c=getchar();
while(c<'0' || c>'9') c=getchar();
while(c>='0' && c<='9') {
res=res*10+c-'0';
c=getchar();
}
return res;
}
struct node {
int to,next;
}edge[MAXN*2];
int head[MAXN],sumedge;
void add(int u,int v){
edge[++sumedge].to=v;
edge[sumedge].next=head[u];
head[u]=sumedge;
}
void addtwo(int u,int v) {
add(u,v);add(v,u);
}
int fa[MAXN][25],dep[MAXN];
int n,m,s;
void dfs(int u) {
for(int i=head[u];i;i=edge[i].next) {
int v=edge[i].to;
if(v!=fa[u][0]) {
fa[v][0]=u;
dep[v]=dep[u]+1;
dfs(v);
}
}
}
int lca(int a,int b) {
if(dep[a]<dep[b]) swap(a,b);
int l=20;
while(dep[a]>dep[b]) {
if(dep[fa[a][l]]>=dep[b]) {
a=fa[a][l];
}
--l;
}
if(a==b) return a;
l=20;
while(fa[a][0]!=fa[b][0]) {
if(fa[a][l]!=fa[b][l]) {
a=fa[a][l];
b=fa[b][l];
}
--l;
}
return fa[a][0];
}
void solve() {
n=read();m=read();s=read();
int x,y;
xiaosiji(i,1,n) {
x=read();
y=read();
addtwo(x,y);
}
dep[s]=1;
dfs(s);
siji(j,1,20) {
siji(i,1,n) {
fa[i][j]=fa[fa[i][j-1]][j-1];
}
}
int a,b;
siji(i,1,m) {
a=read();b=read();
int c=lca(a,b);
printf("%d\n",c);
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
}
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MAXN 500005
//#define ivorysi
using namespace std;
typedef long long ll;
int read() {
int res=0;
char c=getchar();
while(c<'0' || c>'9') c=getchar();
while(c>='0' && c<='9') {
res=res*10+c-'0';
c=getchar();
}
return res;
}
struct node {
int to,next;
}edge[MAXN*2];
struct data {
int to,next,lca;
}qedge[MAXN*2];
int head[MAXN],sumedge,qhead[MAXN],qsum=1,vis[MAXN],fa[MAXN];
int n,m,s;
void add(int u,int v){
edge[++sumedge].to=v;
edge[sumedge].next=head[u];
head[u]=sumedge;
}
void qadd(int u,int v) {
qedge[++qsum].to=v;
qedge[qsum].next=qhead[u];
qhead[u]=qsum;
}
void qaddtwo(int u,int v) {
qadd(u,v);qadd(v,u);
}
void addtwo(int u,int v) {
add(u,v);add(v,u);
}
int getfa(int x) {
return fa[x]==x ? x:fa[x]=getfa(fa[x]);
}
void dfs(int u,int f) {
for(int i=qhead[u];i;i=qedge[i].next) {
int v=qedge[i].to;
if(vis[v]) {
qedge[i].lca=getfa(v);
qedge[i^1].lca=getfa(v);
}
}
vis[u]=1;
for(int i=head[u];i;i=edge[i].next) {
int v=edge[i].to;
if(v!=f) {
dfs(v,u);
fa[getfa(v)]=getfa(u);
}
}
}
void solve() {
n=read();m=read();s=read();
int x,y;
xiaosiji(i,1,n) {
x=read();
y=read();
addtwo(x,y);
}
siji(i,1,m) {
x=read();
y=read();
qaddtwo(x,y);
}
siji(i,1,n) {
fa[i]=i;
}
dfs(s,0);
siji(i,1,n) {
printf("%d\n",qedge[i*2].lca);
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
}
这道题还有求一条点值和最大的路径
要注意每个点的编号和每个点颜色编号的转换
颜色编号的降序其实就是缩点之后的拓扑序
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MAXN 10004
#define MAXM 100005
//#define ivorysi
using namespace std;
typedef long long ll;
int read() {
int res=0;
char c=getchar();
while(c<'0' || c>'9') c=getchar();
while(c>='0' && c<='9') {
res=res*10+c-'0';
c=getchar();
}
return res;
}
struct node {
int to,next;
}edge[MAXM*2];
int head[MAXN],sumedge;
int n,m;
void add(int u,int v){
edge[++sumedge].to=v;
edge[sumedge].next=head[u];
head[u]=sumedge;
}
void addtwo(int u,int v) {
add(u,v);add(v,u);
}
int col[MAXN],tot,instack[MAXN],dfn[MAXN],low[MAXN],cnt;
int val[MAXN],sum[MAXN],dp[MAXN];
vector<int> pos[MAXN];
stack<int> s;
void tarjan(int u) {
instack[u]=1;
dfn[u]=low[u]=++cnt;
s.push(u);
for(int i=head[u];i;i=edge[i].next) {
int v=edge[i].to;
if(!dfn[v]) {
tarjan(v);
low[u]=min(low[v],low[u]);
}
else if(instack[v]==1) {
low[u]=min(dfn[v],low[u]);
}
}
if(low[u]>=dfn[u]) {
++tot;
while(1) {
int x=s.top();s.pop();
pos[tot].push_back(x);
instack[x]=2;
col[x]=tot;
if(x==u) break;
}
}
}
void solve() {
n=read();m=read();
int x,y;
siji(i,1,n) {
val[i]=read();
}
siji(i,1,m) {
x=read();y=read();
add(x,y);
}
siji(i,1,n) {
if(!dfn[i]) {
tarjan(i);
}
}
siji(i,1,n) {
sum[col[i]]+=val[i];
}
siji(i,1,tot) dp[i]+=sum[i];
gongzi(i,tot,1) {
int s=pos[i].size();
xiaosiji(j,0,s) {
int u=pos[i][j];
for(int k=head[u];k;k=edge[k].next) {
int t=edge[k].to;
if(col[t]!=col[u]) {
dp[col[t]]=max(sum[col[t]]+dp[col[u]],dp[col[t]]);
}
}
}
}
int ans=0;
siji(i,1,tot) {
ans=max(ans,dp[i]);
}
printf("%d\n",ans);
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
}
我……我发现我又忘了这玩意了
这个东西注意我们在走到搜索树的儿子边时要用儿子的low更新自身(和tarjan求强连通分量差不多),然后呢,这个点必须不是搜索树的根,然后再来判断这个点的某个儿子能不能走到这个点上面,如果不能说明这个点就是割点
注意判断这个东西不是搜索树的根!!!
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MAXN 10004
#define MAXM 100005
//#define ivorysi
using namespace std;
typedef long long ll;
int read() {
int res=0;
char c=getchar();
while(c<'0' || c>'9') c=getchar();
while(c>='0' && c<='9') {
res=res*10+c-'0';
c=getchar();
}
return res;
}
struct node {
int to,next;
}edge[MAXM*2];
int head[MAXN],sumedge;
int n,m;
void add(int u,int v){
edge[++sumedge].to=v;
edge[sumedge].next=head[u];
head[u]=sumedge;
}
void addtwo(int u,int v) {
add(u,v);add(v,u);
}
int dfn[MAXN],low[MAXN],cnt,ans;
bool ispos[MAXN];
void tarjan(int u,int fa) {
dfn[u]=low[u]=++cnt;
int son=0;
for(int i=head[u];i;i=edge[i].next) {
int v=edge[i].to;
if(!dfn[v]) {
tarjan(v,u);
++son;
low[u]=min(low[v],low[u]);
if(fa!=0 && low[v]>=dfn[u]) {
ispos[u]=1;
}
}
else if(v!=fa){
low[u]=min(dfn[v],low[u]);
}
}
if(fa==0 && son>=2) {
ispos[u]=1;
}
}
void solve() {
n=read();m=read();
int x,y;
siji(i,1,m) {
x=read();y=read();
addtwo(x,y);
}
siji(i,1,n) {
if(!dfn[i]) {
tarjan(i,0);
}
}
siji(i,1,n) {
if(ispos[i]) {
++ans;
}
}
printf("%d\n",ans);
siji(i,1,n) {
if(ispos[i]) {
printf("%d ",i);
}
}
puts("");
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
}
其实我是最近才会的,单个数逆元的求法就是普通的费马小定理快速幂
然后线性的有个递推式
siji(i,2,n) {
inv[i]=(p-p/i)*inv[p%i]%p;
}
证明设
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MAXN 3000005
//#define ivorysi
using namespace std;
typedef long long ll;
ll read() {
ll res=0,neg=1;
char c=getchar();
while(c<'0' || c>'9') {
if(c=='-') neg=-1;
c=getchar();
}
while(c>='0' && c<='9') {
res=res*10+c-'0';
c=getchar();
}
return res*neg;
}
int n,p;
ll inv[MAXN];
void solve() {
n=read();p=read();
inv[1]=1;
printf("%lld\n",inv[1]);
siji(i,2,n) {
inv[i]=(p-p/i)*inv[p%i]%p;
printf("%lld\n",inv[i]);
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
}
证明如下
中的系数
我们发现可以消掉一些系数然后式子就变成了……
能达到的情况只有i=t且j=q
所以
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MAXN 3000005
//#define ivorysi
using namespace std;
typedef long long ll;
ll read() {
ll res=0,neg=1;
char c=getchar();
while(c<'0' || c>'9') {
if(c=='-') neg=-1;
c=getchar();
}
while(c>='0' && c<='9') {
res=res*10+c-'0';
c=getchar();
}
return res*neg;
}
int n,m,p,T;
ll inv[MAXN],fac[MAXN];
ll cnm(int y,int z) {
return fac[y]*inv[z]%p*inv[y-z]%p;
}
ll fpow(ll x,int c) {
ll res=1,t=x;
while(c) {
if(c&1) res=res*t%p;
t=t*t%p;
c>>=1;
}
return res;
}
ll Lucas(int y,int k) {
int q,r;
ll res=1;
while(y>0 && k>0) {
if(y<k) return 0;
r=y%p;q=k%p;
if(r<q) return 0;
res=res*cnm(r,q)%p;
y=y/p;k=k/p;
}
return res;
}
void solve() {
n=read();
m=read();
p=read();
fac[0]=1;
siji(i,1,p-1) {
fac[i]=fac[i-1]*i%p;
}
inv[p-1]=fpow(fac[p-1],p-2);
gongzi(i,p-1,1) {
inv[i-1]=inv[i]*i%p;
}
ll ans=Lucas(n+m,m);
printf("%lld\n",ans);
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
T=read();
while(T--) {
solve();
}
}
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MAXN 1000005
//#define ivorysi
using namespace std;
typedef long long ll;
ll read() {
ll res=0,neg=1;
char c=getchar();
while(c<'0' || c>'9') {
if(c=='-') neg=-1;
c=getchar();
}
while(c>='0' && c<='9') {
res=res*10+c-'0';
c=getchar();
}
return res*neg;
}
char s[MAXN],t[MAXN];
int lens,lent;
int next[MAXN];
void solve() {
scanf("%s%s",s+1,t+1);
lens=strlen(s+1),lent=strlen(t+1);
next[1]=0;
siji(i,2,lent) {
int p=next[i-1];
while(p>0 && t[p+1]!=t[i]) p=next[p];
if(t[p+1]==t[i]) next[i]=p+1;
else next[i]=0;
}
int p=0;
siji(i,1,lens) {
while(p>0 && t[p+1]!=s[i]) p=next[p];
if(t[p+1]==s[i]) ++p;
if(p==lent) {
p=next[p];
printf("%d\n",i-lent+1);
}
}
siji(i,1,lent) {
printf("%d%c",next[i]," \n"[i==lent]);
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
}
注意转移的时候是2×pos-i
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MAXN 25000005
//#define ivorysi
using namespace std;
typedef long long ll;
ll read() {
ll res=0,neg=1;
char c=getchar();
while(c<'0' || c>'9') {
if(c=='-') neg=-1;
c=getchar();
}
while(c>='0' && c<='9') {
res=res*10+c-'0';
c=getchar();
}
return res*neg;
}
char s[MAXN],t[MAXN*2];
int r[MAXN*2];
int lens,lent,ans;
void solve() {
scanf("%s",s+1);
lens=strlen(s+1),lent=strlen(t+1);
siji(i,1,lens) {
t[i*2-1]='$';
t[i*2]=s[i];
}
lent=lens*2+1;
t[lent]='$';
int pos=0,maxright=0;
siji(i,1,lent) {
r[i]=min(r[2*pos-i],maxright-i+1);
r[i]=max(r[i],1);
while(i+r[i]<=lent && i-r[i]>0 && t[i-r[i]]==t[i+r[i]]) ++r[i];
if(i+r[i]-1>maxright) {
maxright=i+r[i]-1;
pos=i;
}
ans=max(ans,r[i]-1);
}
printf("%d\n",ans);
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
}
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MAXN 10000005
#define mod 1000000007
//#define ivorysi
using namespace std;
typedef long long ll;
ll read() {
ll res=0,neg=1;
char c=getchar();
while(c<'0' || c>'9') {
if(c=='-') neg=-1;
c=getchar();
}
while(c>='0' && c<='9') {
res=res*10+c-'0';
c=getchar();
}
return res*neg;
}
int m,n;
int prime[MAXN],cnt;
bool isprime[MAXN];
void solve() {
n=read();m=read();
memset(isprime,1,sizeof(isprime));
isprime[1]=0;
siji(i,2,n) {
if(isprime[i]) {
prime[++cnt]=i;
}
siji(j,1,cnt) {
if(prime[j]>n/i) break;
isprime[i*prime[j]]=0;
if(i%prime[j]==0) break;
}
}
int x;
siji(i,1,m) {
x=read();
if(isprime[x]) {
puts("Yes");
}
else {
puts("No");
}
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
}
假如是极大值,如果val(lm) < val(rm),那么极大值在[l,rm],否则极大值在[lm,r]
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MAXN 10000005
#define mod 1000000007
//#define ivorysi
using namespace std;
typedef long long ll;
ll read() {
ll res=0,neg=1;
char c=getchar();
while(c<'0' || c>'9') {
if(c=='-') neg=-1;
c=getchar();
}
while(c>='0' && c<='9') {
res=res*10+c-'0';
c=getchar();
}
return res*neg;
}
int n;
double a[15],l,r;
double val(double x) {
double tmp=1.0,res=0.0;
siji(i,1,n+1) {
res+=tmp*a[i];
tmp=tmp*x;
}
return res;
}
void solve() {
scanf("%d%lf%lf",&n,&l,&r);
siji(i,1,n+1) {
scanf("%lf",&a[n-i+2]);
}
while(r-l>1e-6) {
double lm=l+(r-l)/3.0;
double rm=r-(r-l)/3.0;
if(val(lm)<val(rm)) l=lm;
else r=rm;
}
printf("%.5lf\n",l);
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
}
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MAXN 10000005
#define mod 1000000007
//#define ivorysi
using namespace std;
typedef long long ll;
ll read() {
ll res=0,neg=1;
char c=getchar();
while(c<'0' || c>'9') {
if(c=='-') neg=-1;
c=getchar();
}
while(c>='0' && c<='9') {
res=res*10+c-'0';
c=getchar();
}
return res*neg;
}
int n,q;
ll g[105][105];
void solve() {
n=read();
siji(i,1,n) {
siji(j,1,n) {
g[i][j]=read();
}
}
siji(k,1,n) {
siji(i,1,n) {
siji(j,1,n) {
g[i][j]=min(g[i][k]+g[k][j],g[i][j]);
}
}
}
int a,b;
q=read();
siji(i,1,q) {
a=read();b=read();
printf("%lld\n",g[a][b]);
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
}
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MAXN 10005
#define MAXM 500005
#define mod 1000000007
#define ivorysi
using namespace std;
typedef long long ll;
ll read() {
ll res=0,neg=1;
char c=getchar();
while(c<'0' || c>'9') {
if(c=='-') neg=-1;
c=getchar();
}
while(c>='0' && c<='9') {
res=res*10+c-'0';
c=getchar();
}
return res*neg;
}
int n,m,s;
struct node {
int to,next,val;
}edge[MAXM*2];
int head[MAXN],sumedge;
void add(int u,int v,int c) {
edge[++sumedge].to=v;
edge[sumedge].next=head[u];
edge[sumedge].val=c;
head[u]=sumedge;
}
ll dis[MAXN],dist[MAXN];
int tr[MAXN*4],pos[MAXN];
bool vis[MAXN];
void build(int u,int l,int r) {
if(l==r) {
tr[u]=l;
pos[l]=u;
return;
}
int m=(l+r)>>1;
build(u<<1,l,m);
build(u<<1|1,m+1,r);
if(dist[tr[u<<1]]<dist[tr[u<<1|1]]) {
tr[u]=tr[u<<1];
}
else {
tr[u]=tr[u<<1|1];
}
}
void change(int x) {
int t=pos[x]>>1;
while(t>=1) {
if(dist[tr[t<<1]]<dist[tr[t<<1|1]]) {
tr[t]=tr[t<<1];
}
else {
tr[t]=tr[t<<1|1];
}
t>>=1;
}
}
void dijkstra(int u) {
siji(i,1,n) dist[i]=0x7fffffff;
dist[u]=0;
build(1,1,n);
int cnt=n;
while(cnt--) {
int now=tr[1];
dis[now]=dist[now];
vis[now]=1;
for(int i=head[now];i;i=edge[i].next) {
int v=edge[i].to,w=edge[i].val;
if((!vis[v]) && dist[v]-w>dist[now]) {
dist[v]=dist[now]+w;
change(v);
}
}
dist[now]=(ll)0x7fffffff+1;
change(now);
}
}
void solve() {
n=read();m=read();s=read();
int a,b,c;
siji(i,1,m) {
a=read();b=read();c=read();
add(a,b,c);
}
dijkstra(s);
siji(i,1,n) {
printf("%lld%c",dis[i]," \n"[i==n]);
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
}
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MAXM 2000005
#define mod 1000000007
//#define ivorysi
using namespace std;
typedef long long ll;
ll read() {
ll res=0,neg=1;
char c=getchar();
while(c<'0' || c>'9') {
if(c=='-') neg=-1;
c=getchar();
}
while(c>='0' && c<='9') {
res=res*10+c-'0';
c=getchar();
}
return res*neg;
}
struct node {
int u,v,val;
bool operator < (const node &b) {
return val<b.val;
}
}edge[MAXM];
int n,m;
int fa[10005];
int getfa(int x) {
return x==fa[x]?x:fa[x]=getfa(fa[x]);
}
void solve() {
n=read();m=read();
int x,y,z;
siji(i,1,m) {
x=read();y=read();z=read();
edge[i].u=x;edge[i].v=y;edge[i].val=z;
}
sort(edge+1,edge+m+1);
siji(i,1,n) {
fa[i]=i;
}
ll ans=0;
siji(i,1,m) {
int l=getfa(edge[i].u),z=getfa(edge[i].v);
if(l!=z) {
fa[l]=z;
ans+=edge[i].val;
}
}
printf("%lld\n",ans);
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
}
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MAXM 2000005
#define MAXN 10005
#define mod 1000000007
//#define ivorysi
using namespace std;
typedef long long ll;
ll read() {
ll res=0,neg=1;
char c=getchar();
while(c<'0' || c>'9') {
if(c=='-') neg=-1;
c=getchar();
}
while(c>='0' && c<='9') {
res=res*10+c-'0';
c=getchar();
}
return res*neg;
}
struct node {
int to,next,val;
}edge[MAXM*4];
int head[10005],sumedge;
void add(int u,int v,int c) {
edge[++sumedge].to=v;
edge[sumedge].next=head[u];
edge[sumedge].val=c;
head[u]=sumedge;
}
bool vis[MAXN];
int n,m,pos[MAXN];
ll dist[MAXN],tr[MAXN*4],ans;
void build(int u,int l,int r) {
if(l==r) {
tr[u]=l;
pos[l]=u;
return ;
}
int m=(l+r)>>1;
build(u<<1,l,m);
build(u<<1|1,m+1,r);
if(dist[tr[u<<1]] < dist[tr[u<<1|1]]) {
tr[u]=tr[u<<1];
}
else {
tr[u]=tr[u<<1|1];
}
}
void change(int x) {
int t=pos[x]>>1;
while(t>=1) {
if(dist[tr[t<<1]]<dist[tr[t<<1|1]]) {
tr[t]=tr[t<<1];
}
else {
tr[t]=tr[t<<1|1];
}
t>>=1;
}
}
void solve() {
n=read();m=read();
int x,y,z;
siji(i,1,m) {
x=read();y=read();z=read();
add(x,y,z);add(y,x,z);
}
siji(i,1,n) dist[i]=0x7fffffff;
dist[1]=0;
build(1,1,n);
int cnt=n;
while(cnt--) {
int u=tr[1];
vis[u]=1;
ans+=dist[u];
for(int i=head[u];i;i=edge[i].next) {
int v=edge[i].to,w=edge[i].val;
if((!vis[v]) && dist[v]>w) {
dist[v]=w;
change(v);
}
}
dist[u]=0x7fffffff;
change(u);
}
printf("%lld\n",ans);
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
}
反正都是距离是负的,我们判断每个点都作为出发点,然后初始的dist是0
然后从每个点开始跑spfa_dfs,如果有负环就回溯
回溯的时候可能错过一些vis点的恢复,所以我们要初始化一遍vis
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MAXN 200005
#define mod 1000000007
//#define ivorysi
using namespace std;
typedef long long ll;
ll read() {
ll res=0,neg=1;
char c=getchar();
while(c<'0' || c>'9') {
if(c=='-') neg=-1;
c=getchar();
}
while(c>='0' && c<='9') {
res=res*10+c-'0';
c=getchar();
}
return res*neg;
}
struct node {
int to,next,val;
}edge[MAXN*4];
int head[MAXN],sumedge,dist[MAXN];
int n,m,T;
void add(int u,int v,int c) {
edge[++sumedge].to=v;
edge[sumedge].next=head[u];
edge[sumedge].val=c;
head[u]=sumedge;
}
void addtwo(int u,int v,int c) {
add(u,v,c);
add(v,u,c);
}
bool vis[MAXN];
bool spfa(int u) {
vis[u]=1;
for(int i=head[u];i;i=edge[i].next) {
int v=edge[i].to,w=edge[i].val;
if(dist[v]>dist[u]+w) {
dist[v]=dist[u]+w;
if(vis[v]) return true;
else {
if(spfa(v)) return true;
}
}
}
vis[u]=0;
return false;
}
void solve() {
memset(head,0,sizeof(head));
//memset(edge,0,sizeof(edge));
sumedge=0;
n=read(),m=read();
int x,y,z;
siji(i,1,m) {
x=read(),y=read(),z=read();
if(z>=0) {
addtwo(x,y,z);
}
else {
add(x,y,z);
}
}
memset(dist,0,sizeof(dist));
memset(vis,0,sizeof(vis));
siji(i,1,n) {
if(spfa(i)) {
puts("YE5");
return;
}
}
puts("N0");
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
T=read();
while(T--) {
solve();
}
}
我发现我并不是很会我当年做的这道题了……
NOI的食物链
我们要把所有的对应关系都考虑上
对于每个点建两个虚拟节点
x y如果可以是同类
x的敌人是y的敌人
x的食物是y的食物
x如果可以吃y
x的食物是y
y的敌人是x
x的敌人是y的食物
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MAXN 100005
//#define ivorysi
using namespace std;
typedef long long ll;
int fa[3*MAXN];
//1-n similar
//n+1-2n its prey
//2n+1-3n its enemy
int n,k;
int ans;
int getfa(int x) {
return x==fa[x] ? x : fa[x]=getfa(fa[x]);
}
void solve() {
scanf("%d%d",&n,&k);
siji(i,1,3*n) {
fa[i]=i;
}
int op,x,y;
siji(i,1,k) {
scanf("%d%d%d",&op,&x,&y);
if(x>n || y>n) {++ans;continue;}
if(op==1) {
int p=getfa(x),q=getfa(y);
if(p==getfa(y+n) || p==getfa(y+2*n)){
++ans;
}
else {
fa[q]=p;
fa[getfa(x+n)]=getfa(y+n);
fa[getfa(x+2*n)]=getfa(y+2*n);
}
}
else {
int p=getfa(x);
if(p==getfa(y) || p==getfa(y+n)) {
++ans;
}
else {
fa[getfa(y+2*n)]=getfa(x);
fa[getfa(x+n)]=getfa(y);
fa[getfa(x+2*n)]=getfa(y+n);
}
}
}
printf("%d\n",ans);
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
}
至今我还是对打标记心怀畏惧……其实标记还可以打很多东西……
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 黄金 Gold
有n个数和5种操作
add a b c:把区间[a,b]内的所有数都增加c
set a b c:把区间[a,b]内的所有数都设为c
sum a b:查询区间[a,b]的区间和
max a b:查询区间[a,b]的最大值
min a b:查询区间[a,b]的最小值
第一行两个整数n,m,第二行n个整数表示这n个数的初始值
接下来m行操作,同题目描述
输出描述 Output Description
对于所有的sum、max、min询问,一行输出一个答案
10 6
3 9 2 8 1 7 5 0 4 6
add 4 9 4
set 2 6 2
add 3 8 2
sum 2 10
max 1 7
min 3 6
49
11
4
1 < n ,m<=100000
这道题教会我一种新的打标记的方式……
线段树是大家喜闻乐见的RMQ,但是这个东西多了一个整体修改
我们针对整体修改,如果一个区间被整体修改了,那么它的加和的lazy必然也没有用了,如果被整体修改之后再加上加和,我们还需要用到这个lazy,所以我们要设两个开关,一个是整体修改的标记,一个是区间加的标记,如果有整体修改的标记先下放它,然后再判断有区间加的标记再下放
注意不能直接把在有整体修改的时候把区间加直接放到修改上,因为两次的区间也不一定覆盖啊……
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MAXN 100005
//#define ivorysi
using namespace std;
typedef long long ll;
ll read() {
ll res=0;
char c=getchar();
while(c<'0' || c>'9') c=getchar();
while(c>='0' && c<='9') {
res=res*10+c-'0';
c=getchar();
}
return res;
}
struct node {
int l,r;
ll minq,maxq,lazy,sum,setq;
bool iscover,isadd;
}tr[MAXN<<2];
ll a[MAXN];
int n,m;
void build(int u,int l,int r) {
tr[u].l=l;
tr[u].r=r;
if(l==r) {
tr[u].sum=a[l];
tr[u].maxq=a[l];
tr[u].minq=a[l];
return;
}
int m=(l+r)>>1;
build(u<<1,l,m);
build(u<<1|1,m+1,r);
tr[u].minq=min(tr[u<<1].minq,tr[u<<1|1].minq);
tr[u].maxq=max(tr[u<<1].maxq,tr[u<<1|1].maxq);
tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum;
}
void pushnode(int u) {
if(tr[u].iscover) {
if(tr[u<<1].l!=tr[u<<1].r) {
tr[u<<1].lazy=0;tr[u<<1].isadd=0;
tr[u<<1].iscover=1;
}
tr[u<<1].setq=tr[u].setq;
tr[u<<1].minq=tr[u<<1].maxq=tr[u].setq;
tr[u<<1].sum=(tr[u<<1].r-tr[u<<1].l+1)*tr[u].setq;
if(tr[u<<1|1].l!=tr[u<<1|1].r) {
tr[u<<1|1].lazy=0;tr[u<<1|1].isadd=0;
tr[u<<1|1].iscover=1;
}
tr[u<<1|1].setq=tr[u].setq;
tr[u<<1|1].minq=tr[u<<1|1].maxq=tr[u].setq;
tr[u<<1|1].sum=(tr[u<<1|1].r-tr[u<<1|1].l+1)*tr[u].setq;
tr[u].iscover=0;
tr[u].setq=0;
}
if(tr[u].isadd){
if(tr[u<<1].l!=tr[u<<1].r) {
tr[u<<1].isadd=1;
tr[u<<1].lazy+=tr[u].lazy;
}
tr[u<<1].minq+=tr[u].lazy;
tr[u<<1].maxq+=tr[u].lazy;
tr[u<<1].sum+=(tr[u<<1].r-tr[u<<1].l+1)*tr[u].lazy;
if(tr[u<<1|1].l!=tr[u<<1|1].r) {
tr[u<<1|1].isadd=1;
tr[u<<1|1].lazy+=tr[u].lazy;
}
tr[u<<1|1].minq+=tr[u].lazy;
tr[u<<1|1].maxq+=tr[u].lazy;
tr[u<<1|1].sum+=(tr[u<<1|1].r-tr[u<<1|1].l+1)*tr[u].lazy;
tr[u].lazy=0;tr[u].isadd=0;
}
}
void update(int u) {
tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum;
tr[u].minq=min(tr[u<<1].minq,tr[u<<1|1].minq);
tr[u].maxq=max(tr[u<<1].maxq,tr[u<<1|1].maxq);
}
void add(int u,int l,int r,ll x) {
if(tr[u].l==l && tr[u].r==r) {
tr[u].isadd=1;
tr[u].lazy+=x;
tr[u].minq+=x;
tr[u].maxq+=x;
tr[u].sum+=(tr[u].r-tr[u].l+1)*x;
return;
}
pushnode(u);
int m=(tr[u].l+tr[u].r)>>1;
if(r<=m) {
add(u<<1,l,r,x);
}
else if(l>m) {
add(u<<1|1,l,r,x);
}
else {
add(u<<1,l,m,x);
add(u<<1|1,m+1,r,x);
}
update(u);
}
void change(int u,int l,int r,ll c) {
if(tr[u].l==l && tr[u].r==r) {
tr[u].lazy=0;
tr[u].isadd=0;
tr[u].iscover=1;
tr[u].setq=c;
tr[u].minq=tr[u].maxq=c;
tr[u].sum=(tr[u].r-tr[u].l+1)*c;
return;
}
pushnode(u);
int m=(tr[u].l+tr[u].r)>>1;
if(r<=m) {
change(u<<1,l,r,c);
}
else if(l>m) {
change(u<<1|1,l,r,c);
}
else {
change(u<<1,l,m,c);
change(u<<1|1,m+1,r,c);
}
update(u);
}
ll qmax(int u,int l,int r) {
if(tr[u].l==l && tr[u].r==r) {
return tr[u].maxq;
}
int m=(tr[u].l+tr[u].r)>>1;
pushnode(u);
if(r<=m) {
return qmax(u<<1,l,r);
}
else if(l>m) {
return qmax(u<<1|1,l,r);
}
else {
return max(qmax(u<<1,l,m),qmax(u<<1|1,m+1,r));
}
update(u);
}
ll qmin(int u,int l,int r) {
if(tr[u].l==l && tr[u].r==r) {
return tr[u].minq;
}
int m=(tr[u].l+tr[u].r)>>1;
pushnode(u);
if(r<=m) {
return qmin(u<<1,l,r);
}
else if(l>m) {
return qmin(u<<1|1,l,r);
}
else {
return min(qmin(u<<1,l,m),qmin(u<<1|1,m+1,r));
}
update(u);
}
ll qsum(int u,int l,int r) {
if(tr[u].l==l && tr[u].r==r) {
return tr[u].sum;
}
int m=(tr[u].l+tr[u].r)>>1;
pushnode(u);
if(r<=m) {
return qsum(u<<1,l,r);
}
else if(l>m) {
return qsum(u<<1|1,l,r);
}
else {
return qsum(u<<1,l,m)+qsum(u<<1|1,m+1,r);
}
update(u);
}
char c[15];
void solve() {
n=read();m=read();
siji(i,1,n) {
a[i]=read();
}
build(1,1,n);
int a,b,x;
siji(i,1,m) {
scanf("%s",c+1);
a=read();b=read();
if(c[1]=='a') {
x=read();
add(1,a,b,x);
}
else if(c[1]=='s' && c[2]=='e') {
x=read();
change(1,a,b,x);
}
else if(c[1]=='s' && c[2]=='u') {
printf("%lld\n",qsum(1,a,b));
}
else if(c[1]=='m' && c[2]=='i') {
printf("%lld\n",qmin(1,a,b));
}
else {
printf("%lld\n",qmax(1,a,b));
}
}
}
int main() {
solve();
}
区间修改,区间查询……不过这个题是单点,但是道理一样
我们考虑查分,每个查分的值都乘上整个序列,再删除掉重复的部分,两端分开维护
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MAXN 500005
//#define ivorysi
using namespace std;
typedef long long ll;
ll read() {
ll res=0,neg=1;
char c=getchar();
while(c<'0' || c>'9') {
if(c=='-') neg=-1;
c=getchar();
}
while(c>='0' && c<='9') {
res=res*10+c-'0';
c=getchar();
}
return res*neg;
}
int n,m;
ll a[MAXN],sum[MAXN];
ll tr1[MAXN],tr2[MAXN];
int lowbit(int x) {return x&(-x);}
void change(ll *cur,int pos,ll k) {
while(pos<=n) {
cur[pos]+=k;
pos+=lowbit(pos);
}
}
ll _query(ll *cur,int pos) {
ll res=0;
while(pos>0) {
res+=cur[pos];
pos-=lowbit(pos);
}
return res;
}
ll query(int pos) {
ll res=_query(tr1,pos)*pos+_query(tr2,pos)+sum[pos];
return res;
}
void solve() {
n=read();m=read();
siji(i,1,n) {
a[i]=read();
sum[i]=sum[i-1]+a[i];
}
int op,x,y,k;
while(m--) {
op=read();
if(op==1) {
x=read();y=read();k=read();
change(tr1,x,k);
change(tr1,y+1,-k);
change(tr2,x,((ll)x-1)*(-k));
change(tr2,y+1,(ll)y*k);
}
else {
x=read();
ll ans=query(x)-query(x-1);
printf("%lld\n",ans);
}
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
}
简单易写的RMQ
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MAXN 1000005
//define ivorysi
using namespace std;
typedef long long ll;
ll read() {
ll res=0,neg=1;
char c=getchar();
while(c<'0' || c>'9') {
if(c=='-') neg=-1;
c=getchar();
}
while(c>='0' && c<='9') {
res=res*10+c-'0';
c=getchar();
}
return res*neg;
}
int a[100006];
int n,m;
int st[100006][25];
int log2[100006];
int calc(int c) {
int l=0;
while(c) {
l++;
c>>=1;
}
return l-1;
}
void solve() {
n=read();
m=read();
siji(i,1,n) {
a[i]=read();
st[i][0]=a[i];
log2[i]=calc(i);
}
siji(j,1,20) {
siji(i,1,n) {
if((i+(1<<j)-1)>n) break;
st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]);
}
}
int a,b;
siji(i,1,m) {
a=read();b=read();
int len=log2[b-a+1];
int ans=max(st[a][len],st[b-(1<<len)+1][len]);
printf("%d\n",ans);
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
}
如题,已知一个数列,你需要进行下面两种操作:
1.将某区间每一个数加上x
2.将某区间每一个数乘上x
3.求出某区间每一个数的和
第一行包含三个整数N、M、P,分别表示该数列数字的个数、操作的总个数和模数。
第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。
接下来M行每行包含3或4个整数,表示一个操作,具体如下:
操作1: 格式:1 x y k 含义:将区间[x,y]内每个数乘上k
操作2: 格式:2 x y k 含义:将区间[x,y]内每个数加上k
操作3: 格式:3 x y 含义:输出区间[x,y]内每个数的和对P取模所得的结果
输出包含若干行整数,即为所有操作3的结果。
5 5 38
1 5 4 2 3
2 1 4 1
3 2 5
1 2 4 2
2 3 5 5
3 1 4
17
2
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=8,M<=10
对于70%的数据:N<=1000,M<=10000
对于100%的数据:N<=100000,M<=100000
我们要维护两个标记,一个是乘的标记mul,一个是加的标记add
更新乘法的时候需要用add×mul mul*mul
然后更新加法的时候add+add
pushnode的时候乘法标记直接相乘
加法标记乘上乘法标记再加上加法标记
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define MAXN 100005
#define mod 1000000007
//#define ivorysi
using namespace std;
typedef long long ll;
ll read() {
ll res=0,neg=1;
char c=getchar();
while(c<'0' || c>'9') {
if(c=='-') neg=-1;
c=getchar();
}
while(c>='0' && c<='9') {
res=res*10+c-'0';
c=getchar();
}
return res*neg;
}
int n;
ll a[MAXN],m,P;
struct node {
ll add,mul,sum;
int l,r;
}tr[MAXN*8];
void update(int u) {
tr[u].sum=(tr[u<<1].sum+tr[u<<1|1].sum)%P;
}
void build(int u,int l,int r) {
tr[u].l=l;
tr[u].r=r;
tr[u].mul=1;
tr[u].add=0;
if(l==r) {
tr[u].sum=a[l];
return;
}
int mid=(l+r)>>1;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
update(u);
}
void push_down(int u) {
int l=tr[u].l,r=tr[u].r;
tr[u<<1].sum=tr[u<<1].sum*tr[u].mul%P;
tr[u<<1|1].sum=tr[u<<1|1].sum*tr[u].mul%P;
tr[u<<1].mul*=tr[u].mul;
tr[u<<1].mul%=P;
tr[u<<1|1].mul*=tr[u].mul;
tr[u<<1|1].mul%=P;
int mid=(tr[u].l+tr[u].r)>>1;
tr[u<<1].sum=(tr[u<<1].sum+tr[u].add*(mid-l+1)%P)%P;
tr[u<<1|1].sum=(tr[u<<1|1].sum+tr[u].add*(r-mid)%P)%P;
tr[u<<1].add=(tr[u<<1].add*tr[u].mul%P+tr[u].add)%P;
tr[u<<1|1].add=(tr[u<<1|1].add*tr[u].mul%P+tr[u].add)%P;
tr[u].mul=1;tr[u].add=0;
}
void change(int u,int ql,int qr,ll k,bool is_mul) {
if(ql==tr[u].l && qr==tr[u].r) {
if(is_mul) {
tr[u].add=tr[u].add*k%P;
tr[u].mul=tr[u].mul*k%P;
tr[u].sum=tr[u].sum*k%P;
}
else {
tr[u].add=(tr[u].add+k)%P;
tr[u].sum=(tr[u].sum+(tr[u].r-tr[u].l+1)*k%P)%P;
}
return;
}
push_down(u);
int mid=(tr[u].l+tr[u].r)>>1;
if(qr<=mid) {
change(u<<1,ql,qr,k,is_mul);
}
else if(ql>mid) {
change(u<<1|1,ql,qr,k,is_mul);
}
else {
change(u<<1,ql,mid,k,is_mul);
change(u<<1|1,mid+1,qr,k,is_mul);
}
update(u);
}
ll query(int u,int ql,int qr) {
if(tr[u].l==ql && tr[u].r==qr) {
return tr[u].sum;
}
push_down(u);
int mid=(tr[u].l+tr[u].r)>>1;
if(qr<=mid) {
return query(u<<1,ql,qr);
}
else if(ql>mid) {
return query(u<<1|1,ql,qr);
}
else {
return (query(u<<1,ql,mid)+query(u<<1|1,mid+1,qr))%P;
}
}
void solve() {
n=read();m=read();P=read();
siji(i,1,n) a[i]=read();
build(1,1,n);
ll x,y,k,op;
siji(i,1,m) {
op=read();
x=read();y=read();
if(op==1) {
k=read();
change(1,x,y,k,1);
}
else if(op==2) {
k=read();
change(1,x,y,k,0);
}
else {
ll res=query(1,x,y);
printf("%lld\n",res);
}
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
}